Ensure permanent face is recreated after network connectivity changes

Change-Id: I12efc7e81befa035488a09692aaa6412471d3c17
Refs: #3443
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9ac597f..cc07744 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
     <uses-permission android:name="android.permission.READ_LOGS" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
     <application
         android:allowBackup="true"
@@ -33,6 +34,15 @@
             </intent-filter>
         </service>
 
+        <receiver
+            android:name="net.named_data.nfd.utils.ConnectivityChangeReceiver"
+            android:label="ConnectivityChangeReceiver" >
+            <intent-filter>
+                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
     </application>
 
 </manifest>
diff --git a/app/src/main/java/net/named_data/nfd/service/NfdService.java b/app/src/main/java/net/named_data/nfd/service/NfdService.java
index 55a4f9d..3ab102d 100644
--- a/app/src/main/java/net/named_data/nfd/service/NfdService.java
+++ b/app/src/main/java/net/named_data/nfd/service/NfdService.java
@@ -128,6 +128,7 @@
     G.Log(TAG, "NFDService::onStartCommand()");
 
     serviceStartNfd();
+    createPermanentFaceUriAndRoute();
 
     // Service is restarted when killed.
     // Pending intents delivered; null intent redelivered otherwise.
@@ -184,32 +185,24 @@
       // Keep Service alive; In event when service is started
       // from a Handler's message through binding with the service.
       startService(new Intent(this, NfdService.class));
-
-      // Restore PermanentFaceUriAndRoute once NFD is running
-      onNfdStart(new Runnable() {
-        @Override
-        public void run() {
-          createPermanentFaceUriAndRoute(getApplicationContext());
-        }
-      });
-
       G.Log(TAG, "serviceStartNfd()");
     } else {
       G.Log(TAG, "serviceStartNfd(): NFD Service already running!");
     }
   }
 
-  private void onNfdStart(final Runnable task) {
+  private void createPermanentFaceUriAndRoute() {
     final long checkInterval = 1000;
     if (isNfdRunning()) {
-      G.Log(TAG, "onNfdStart: NFD is running, start executing task.");
-      task.run();
+      G.Log(TAG, "createPermanentFaceUriAndRoute: NFD is running, start executing task.");
+      new FaceCreateAsyncTask(getApplicationContext()).execute();
+      new RouteCreateAsyncTask(getApplicationContext()).execute();
     } else {
-      G.Log(TAG, "onNfdStart: NFD is not started yet, delay " + String.valueOf(checkInterval) + " ms.");
+      G.Log(TAG, "createPermanentFaceUriAndRoute: NFD is not started yet, delay " + String.valueOf(checkInterval) + " ms.");
       m_handler.postDelayed(new Runnable() {
         @Override
         public void run() {
-          onNfdStart(task);
+          createPermanentFaceUriAndRoute();
         }
       }, checkInterval);
     }
@@ -297,15 +290,6 @@
   }
 
   /**
-   * create all permanent faces and routes in the background
-   * @param ctx: Application Context
-   */
-  public static void createPermanentFaceUriAndRoute(Context ctx) {
-    new FaceCreateAsyncTask(ctx).execute();
-    new RouteCreateAsyncTask(ctx).execute();
-  }
-
-  /**
    * Message handler for the the NFD Service.
    */
   private class NfdServiceMessageHandler extends Handler {
diff --git a/app/src/main/java/net/named_data/nfd/utils/ConnectivityChangeReceiver.java b/app/src/main/java/net/named_data/nfd/utils/ConnectivityChangeReceiver.java
new file mode 100644
index 0000000..be9e2ee
--- /dev/null
+++ b/app/src/main/java/net/named_data/nfd/utils/ConnectivityChangeReceiver.java
@@ -0,0 +1,69 @@
+/* -*- Mode:jde; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2015-2016 Regents of the University of California
+ * <p>
+ * This file is part of NFD (Named Data Networking Forwarding Daemon) Android.
+ * See AUTHORS.md for complete list of NFD Android authors and contributors.
+ * <p>
+ * NFD Android is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ * <p>
+ * NFD Android is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU General Public License along with
+ * NFD Android, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.named_data.nfd.utils;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+import net.named_data.nfd.service.NfdService;
+
+/**
+ * ConnectivityChangeReceiver monitors network connectivity changes and update
+ * face and route list accordingly.
+ */
+public class ConnectivityChangeReceiver extends BroadcastReceiver {
+  private static final String TAG = ConnectivityChangeReceiver.class.getName();
+
+  @Override
+  public void
+  onReceive(Context context, Intent intent) {
+    NetworkInfo network = getNetworkInfo(context);
+    if (null == network) {
+      G.Log(TAG, "Connection lost");
+      onConnectionLost(context);
+    } else {
+      G.Log(TAG, "Connection changed");
+      onChange(context, network);
+    }
+  }
+
+  private static NetworkInfo getNetworkInfo(Context applicationContext) {
+    ConnectivityManager cm = (ConnectivityManager) applicationContext
+        .getSystemService(Context.CONNECTIVITY_SERVICE);
+    return cm.getActiveNetworkInfo();
+  }
+
+  private void
+  onChange(Context context, NetworkInfo networkInfo) {
+    if (networkInfo.isConnected()) {
+      G.Log(TAG, "Network is connected");
+      // (re-)start service, triggering (re-)creation of permanent faces and routes
+      context.startService(new Intent(context, NfdService.class));
+    }
+  }
+
+  private void
+  onConnectionLost(Context context) {
+    // nothing to do: face/routes should disappear by themselves
+  }
+}