Add NetworkFactory names and unregistration.

Some Factories come and go (Telephony) and so they need to be able to unregister.
Also, debugging is tough when the factories are anonymous, so add names for logging.

Lastly, only send single set of NetworkRequests to a newly registered NetworkFactory
and only send the requests.

Change-Id: I717d63363f25c446f8ecf38d933b1a35d744af6e
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1837335..80a9598 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1655,9 +1655,16 @@
     }
 
     /** {@hide} */
-    public void registerNetworkFactory(Messenger messenger) {
+    public void registerNetworkFactory(Messenger messenger, String name) {
         try {
-            mService.registerNetworkFactory(messenger);
+            mService.registerNetworkFactory(messenger, name);
+        } catch (RemoteException e) { }
+    }
+
+    /** {@hide} */
+    public void unregisterNetworkFactory(Messenger messenger) {
+        try {
+            mService.unregisterNetworkFactory(messenger);
         } catch (RemoteException e) { }
     }
 
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 885b8b6..d97b1e9 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -153,7 +153,9 @@
 
     void setAirplaneMode(boolean enable);
 
-    void registerNetworkFactory(in Messenger messenger);
+    void registerNetworkFactory(in Messenger messenger, in String name);
+
+    void unregisterNetworkFactory(in Messenger messenger);
 
     void registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
             in NetworkCapabilities nc, int score);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index cc132be..af53fef 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -398,7 +398,7 @@
 
     /**
      * used internally when registering NetworkFactories
-     * obj = Messenger
+     * obj = NetworkFactoryInfo
      */
     private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
 
@@ -434,6 +434,13 @@
      */
     private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
 
+    /**
+     * used internally when registering NetworkFactories
+     * obj = Messenger
+     */
+    private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
+
+
     /** Handler used for internal events. */
     final private InternalHandler mHandler;
     /** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -2889,6 +2896,14 @@
             return;
         }
 
+        pw.println("NetworkFactories for:");
+        pw.increaseIndent();
+        for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+            pw.println(nfi.name);
+        }
+        pw.decreaseIndent();
+        pw.println();
+
         NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
         pw.print("Active default network: ");
         if (defaultNai == null) {
@@ -2983,6 +2998,7 @@
                     if (nai == null) {
                         loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
                     } else {
+                        if (VDBG) log("Update of Linkproperties for " + nai.name());
                         LinkProperties oldLp = nai.linkProperties;
                         nai.linkProperties = (LinkProperties)msg.obj;
                         updateLinkProperties(nai, oldLp);
@@ -3096,18 +3112,19 @@
 
     private void handleAsyncChannelHalfConnect(Message msg) {
         AsyncChannel ac = (AsyncChannel) msg.obj;
-        if (mNetworkFactories.contains(ac)) {
+        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                 if (VDBG) log("NetworkFactory connected");
                 // A network factory has connected.  Send it all current NetworkRequests.
                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+                    if (nri.isRequest == false) continue;
                     NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                     ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
                             (nai != null ? nai.currentScore : 0), 0, nri.request);
                 }
             } else {
                 loge("Error connecting NetworkFactory");
-                mNetworkFactories.remove(ac);
+                mNetworkFactoryInfos.remove(msg.obj);
             }
         } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -3214,8 +3231,8 @@
         mNetworkRequests.put(nri.request, nri);
         if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
             if (DBG) log("sending new NetworkRequest to factories");
-            for (AsyncChannel ac : mNetworkFactories) {
-                ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+            for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+                nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
             }
         }
     }
@@ -3236,8 +3253,8 @@
             }
 
             if (nri.isRequest) {
-                for (AsyncChannel factory : mNetworkFactories) {
-                    factory.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+                for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+                    nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
                 }
 
                 if (affectedNetwork != null) {
@@ -3356,7 +3373,11 @@
                     break;
                 }
                 case EVENT_REGISTER_NETWORK_FACTORY: {
-                    handleRegisterNetworkFactory((Messenger)msg.obj);
+                    handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
+                    break;
+                }
+                case EVENT_UNREGISTER_NETWORK_FACTORY: {
+                    handleUnregisterNetworkFactory((Messenger)msg.obj);
                     break;
                 }
                 case EVENT_REGISTER_NETWORK_AGENT: {
@@ -5222,10 +5243,22 @@
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
     }
 
-    private final ArrayList<AsyncChannel> mNetworkFactories = new ArrayList<AsyncChannel>();
+    private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
+            new HashMap<Messenger, NetworkFactoryInfo>();
     private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
             new HashMap<NetworkRequest, NetworkRequestInfo>();
 
+    private static class NetworkFactoryInfo {
+        public final String name;
+        public final Messenger messenger;
+        public final AsyncChannel asyncChannel;
+
+        public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
+            this.name = name;
+            this.messenger = messenger;
+            this.asyncChannel = asyncChannel;
+        }
+    }
 
     private class NetworkRequestInfo implements IBinder.DeathRecipient {
         static final boolean REQUEST = true;
@@ -5263,6 +5296,11 @@
                     request + ", " + mBinder + ")");
             releaseNetworkRequest(request);
         }
+
+        public String toString() {
+            return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
+                    mPid + " for " + request;
+        }
     }
 
     @Override
@@ -5326,24 +5364,31 @@
     }
 
     @Override
-    public void registerNetworkFactory(Messenger messenger) {
+    public void registerNetworkFactory(Messenger messenger, String name) {
         enforceConnectivityInternalPermission();
-        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, messenger));
+        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
     }
 
-    private void handleRegisterNetworkFactory(Messenger messenger) {
-        if (VDBG) log("Got NetworkFactory Messenger");
-        AsyncChannel ac = new AsyncChannel();
-        mNetworkFactories.add(ac);
-        ac.connect(mContext, mTrackerHandler, messenger);
-        for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            if (nri.isRequest) {
-                int score = 0;
-                NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
-                if (currentNetwork != null) score = currentNetwork.currentScore;
-                ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
-            }
+    private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
+        if (VDBG) log("Got NetworkFactory Messenger for " + nfi.name);
+        mNetworkFactoryInfos.put(nfi.messenger, nfi);
+        nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+    }
+
+    @Override
+    public void unregisterNetworkFactory(Messenger messenger) {
+        enforceConnectivityInternalPermission();
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
+    }
+
+    private void handleUnregisterNetworkFactory(Messenger messenger) {
+        NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
+        if (nfi == null) {
+            if (VDBG) log("Failed to find Messenger in unregisterNetworkFactory");
+            return;
         }
+        if (VDBG) log("unregisterNetworkFactory for " + nfi.name);
     }
 
     /**
@@ -5535,8 +5580,8 @@
 
     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
         if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
-        for (AsyncChannel ac : mNetworkFactories) {
-            ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+        for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+            nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
         }
     }