Merge "Add ConnectivityManager.registerNetworkCallback(NetworkRequest, PendingIntent)" into mnc-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a2ca41c..b9f7365 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2461,7 +2461,7 @@
      * Intent to reserve the network or it will be released shortly after the Intent
      * is processed.
      * <p>
-     * If there is already an request for this Intent registered (with the equality of
+     * If there is already a request for this Intent registered (with the equality of
      * two Intents defined by {@link Intent#filterEquals}), then it will be removed and
      * replaced by this one, effectively releasing the previous {@link NetworkRequest}.
      * <p>
@@ -2521,6 +2521,44 @@
     }
 
     /**
+     * Registers a PendingIntent to be sent when a network is available which satisfies the given
+     * {@link NetworkRequest}.
+     *
+     * This function behaves identically to the version that takes a NetworkCallback, but instead
+     * of {@link NetworkCallback} a {@link PendingIntent} is used.  This means
+     * the request may outlive the calling application and get called back when a suitable
+     * network is found.
+     * <p>
+     * The operation is an Intent broadcast that goes to a broadcast receiver that
+     * you registered with {@link Context#registerReceiver} or through the
+     * &lt;receiver&gt; tag in an AndroidManifest.xml file
+     * <p>
+     * The operation Intent is delivered with two extras, a {@link Network} typed
+     * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest}
+     * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing
+     * the original requests parameters.
+     * <p>
+     * If there is already a request for this Intent registered (with the equality of
+     * two Intents defined by {@link Intent#filterEquals}), then it will be removed and
+     * replaced by this one, effectively releasing the previous {@link NetworkRequest}.
+     * <p>
+     * The request may be released normally by calling
+     * {@link #releaseNetworkRequest(android.app.PendingIntent)}.
+     * <p>This method requires the caller to hold the permission
+     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+     * @param request {@link NetworkRequest} describing this request.
+     * @param operation Action to perform when the network is available (corresponds
+     *                  to the {@link NetworkCallback#onAvailable} call.  Typically
+     *                  comes from {@link PendingIntent#getBroadcast}. Cannot be null.
+     */
+    public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
+        checkPendingIntent(operation);
+        try {
+            mService.pendingListenForNetwork(request.networkCapabilities, operation);
+        } catch (RemoteException e) {}
+    }
+
+    /**
      * Requests bandwidth update for a given {@link Network} and returns whether the update request
      * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying
      * network connection for updated bandwidth information. The caller will be notified via
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 08b7184..5aae713 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -326,7 +326,7 @@
 
     /**
      * used to add a network request with a pending intent
-     * includes a NetworkRequestInfo
+     * obj = NetworkRequestInfo
      */
     private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
 
@@ -356,6 +356,12 @@
      */
     private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
 
+    /**
+     * used to add a network listener with a pending intent
+     * obj = NetworkRequestInfo
+     */
+    private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
+
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -2484,7 +2490,8 @@
                     handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
                     break;
                 }
-                case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
+                case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
+                case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
                     handleRegisterNetworkRequestWithIntent(msg);
                     break;
                 }
@@ -3693,6 +3700,18 @@
     @Override
     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
             PendingIntent operation) {
+        checkNotNull(operation, "PendingIntent cannot be null.");
+        if (!hasWifiNetworkListenPermission(networkCapabilities)) {
+            enforceAccessPermission();
+        }
+
+        NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
+                networkCapabilities), TYPE_NONE, nextNetworkRequestId());
+        if (DBG) log("pendingListenForNetwork for " + networkRequest + " to trigger " + operation);
+        NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
+                NetworkRequestInfo.LISTEN);
+
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
     }
 
     @Override