Use LinkAddress in address notifications.

Currently address{Updated,Removed} pass in the address as a
string such as "fe80::1/64". Use LinkAddresses instead, since
that's what it is.

This makes the code more robust in the unlikely case that netd
passes in an invalid string. In the future we can move flags and
scope into the LinkAddress itself and simplify the code further.

Bug: 9180552
Change-Id: I66599f9529cf421caa7676fdd0141bb110b8589e
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index c720c7b..405a897 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.net.LinkAddress;
+
 /**
  * Callback class for receiving events from an INetworkManagementService
  *
@@ -62,7 +64,7 @@
      * @param flags The address flags.
      * @param scope The address scope.
      */
-    void addressUpdated(String address, String iface, int flags, int scope);
+    void addressUpdated(in LinkAddress address, String iface, int flags, int scope);
 
     /**
      * An interface address has been removed
@@ -72,7 +74,7 @@
      * @param flags The address flags.
      * @param scope The address scope.
      */
-    void addressRemoved(String address, String iface, int flags, int scope);
+    void addressRemoved(in LinkAddress address, String iface, int flags, int scope);
 
     /**
      * A networking quota limit has been reached. The quota might not
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
index a02c602..1e80a21 100644
--- a/core/java/com/android/server/net/BaseNetworkObserver.java
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -17,6 +17,7 @@
 package com.android.server.net;
 
 import android.net.INetworkManagementEventObserver;
+import android.net.LinkAddress;
 
 /**
  * Base {@link INetworkManagementEventObserver} that provides no-op
@@ -36,12 +37,12 @@
     }
 
     @Override
-    public void addressUpdated(String address, String iface, int flags, int scope) {
+    public void addressUpdated(LinkAddress address, String iface, int flags, int scope) {
         // default no-op
     }
 
     @Override
-    public void addressRemoved(String address, String iface, int flags, int scope) {
+    public void addressRemoved(LinkAddress address, String iface, int flags, int scope) {
         // default no-op
     }
 
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 8089fbc..40ea49e 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -405,7 +405,7 @@
     /**
      * Notify our observers of a new or updated interface address.
      */
-    private void notifyAddressUpdated(String address, String iface, int flags, int scope) {
+    private void notifyAddressUpdated(LinkAddress address, String iface, int flags, int scope) {
         final int length = mObservers.beginBroadcast();
         for (int i = 0; i < length; i++) {
             try {
@@ -420,7 +420,7 @@
     /**
      * Notify our observers of a deleted interface address.
      */
-    private void notifyAddressRemoved(String address, String iface, int flags, int scope) {
+    private void notifyAddressRemoved(LinkAddress address, String iface, int flags, int scope) {
         final int length = mObservers.beginBroadcast();
         for (int i = 0; i < length; i++) {
             try {
@@ -537,17 +537,21 @@
 
                     int flags;
                     int scope;
+                    LinkAddress address;
                     try {
                         flags = Integer.parseInt(cooked[5]);
                         scope = Integer.parseInt(cooked[6]);
-                    } catch(NumberFormatException e) {
-                        throw new IllegalStateException(errorMessage);
+                        address = new LinkAddress(cooked[3]);
+                    } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.
+                        throw new IllegalStateException(errorMessage, e);
+                    } catch(IllegalArgumentException e) {  // Malformed IP address.
+                        throw new IllegalStateException(errorMessage, e);
                     }
 
                     if (cooked[2].equals("updated")) {
-                        notifyAddressUpdated(cooked[3], cooked[4], flags, scope);
+                        notifyAddressUpdated(address, cooked[4], flags, scope);
                     } else {
-                        notifyAddressRemoved(cooked[3], cooked[4], flags, scope);
+                        notifyAddressRemoved(address, cooked[4], flags, scope);
                     }
                     return true;
                     // break;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
index 4385dcd..a78e7b6 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.content.Context;
+import android.net.LinkAddress;
 import android.net.LocalSocket;
 import android.net.LocalServerSocket;
 import android.os.Binder;
@@ -157,19 +158,22 @@
          * IP address changes.
          */
         sendMessage("614 Address updated fe80::1/64 wlan0 128 253");
-        expectSoon(observer).addressUpdated("fe80::1/64", "wlan0", 128, 253);
+        expectSoon(observer).addressUpdated(
+                new LinkAddress("fe80::1/64"), "wlan0", 128, 253);
 
-        // There is no "added".
+        // There is no "added", so we take this as "removed".
         sendMessage("614 Address added fe80::1/64 wlan0 128 253");
-        expectSoon(observer).addressRemoved("fe80::1/64", "wlan0", 128, 253);
+        expectSoon(observer).addressRemoved(
+                new LinkAddress("fe80::1/64"), "wlan0", 128, 253);
 
         sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0");
-        expectSoon(observer).addressRemoved("2001:db8::1/64", "wlan0", 1, 0);
+        expectSoon(observer).addressRemoved(
+                new LinkAddress("2001:db8::1/64"), "wlan0", 1, 0);
 
         sendMessage("614 Address removed 2001:db8::1/64 wlan0 1");
         // Not enough arguments.
 
-        sendMessage("666 Address added 2001:db8::1/64 wlan0 1 0");
+        sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0");
         // Invalid code.
 
 
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 4bc3dda..60c7f03 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -240,24 +240,24 @@
         }
 
         @Override
-        public void addressUpdated(String address, String iface, int flags, int scope) {
+        public void addressUpdated(LinkAddress address, String iface, int flags, int scope) {
             if (mWifiStateMachine.mInterfaceName.equals(iface)) {
                 if (DBG) {
                     log("addressUpdated: " + address + " on " + iface +
                         " flags " + flags + " scope " + scope);
                 }
-                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, new LinkAddress(address));
+                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_UPDATED, address);
             }
         }
 
         @Override
-        public void addressRemoved(String address, String iface, int flags, int scope) {
+        public void addressRemoved(LinkAddress address, String iface, int flags, int scope) {
             if (mWifiStateMachine.mInterfaceName.equals(iface)) {
                 if (DBG) {
                     log("addressRemoved: " + address + " on " + iface +
                         " flags " + flags + " scope " + scope);
                 }
-                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, new LinkAddress(address));
+                mWifiStateMachine.sendMessage(CMD_IP_ADDRESS_REMOVED, address);
             }
         }
     }