From 02fe11eba35c8d2ea0c8b293241d60520f7943cd Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Mon, 23 Jun 2014 11:40:00 -0700 Subject: [PATCH] Add Network inspection API. Adds getNetworksNetworkInfo. Adds getAllNetworks. Cleans up some synchronization issues. Change-Id: I82c7a4b554e3c6c1adfe6027cc54b028ed6dbac9 --- .../java/android/net/ConnectivityManager.java | 42 ++++++- .../android/net/IConnectivityManager.aidl | 2 + .../android/server/ConnectivityService.java | 118 ++++++++++++++---- 3 files changed, 138 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index fb4912f270..2dd467cc96 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -743,7 +743,7 @@ public class ConnectivityManager { * network type or {@code null} if the type is not * supported by the device. * - *

This method requires the call to hold the permission + *

This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. */ public NetworkInfo getNetworkInfo(int networkType) { @@ -754,6 +754,27 @@ public class ConnectivityManager { } } + /** + * Returns connection status information about a particular + * Network. + * + * @param network {@link Network} specifying which network + * in which you're interested. + * @return a {@link NetworkInfo} object for the requested + * network or {@code null} if the {@code Network} + * is not valid. + * + *

This method requires the caller to hold the permission + * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. + */ + public NetworkInfo getNetworkInfo(Network network) { + try { + return mService.getNetworkInfoForNetwork(network); + } catch (RemoteException e) { + return null; + } + } + /** * Returns connection status information about all network * types supported by the device. @@ -761,7 +782,7 @@ public class ConnectivityManager { * @return an array of {@link NetworkInfo} objects. Check each * {@link NetworkInfo#getType} for which type each applies. * - *

This method requires the call to hold the permission + *

This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. */ public NetworkInfo[] getAllNetworkInfo() { @@ -772,6 +793,23 @@ public class ConnectivityManager { } } + /** + * Returns an array of all {@link Network} currently tracked by the + * framework. + * + * @return an array of {@link Network} objects. + * + *

This method requires the caller to hold the permission + * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. + */ + public Network[] getAllNetworks() { + try { + return mService.getAllNetworks(); + } catch (RemoteException e) { + return null; + } + } + /** * Returns details about the Provisioning or currently active default data network. When * connected, this network is the default route for outgoing connections. diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 51d9b8ca45..ca722b7f99 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -48,7 +48,9 @@ interface IConnectivityManager NetworkInfo getActiveNetworkInfo(); NetworkInfo getActiveNetworkInfoForUid(int uid); NetworkInfo getNetworkInfo(int networkType); + NetworkInfo getNetworkInfoForNetwork(in Network network); NetworkInfo[] getAllNetworkInfo(); + Network[] getAllNetworks(); NetworkInfo getProvisioningOrActiveNetworkInfo(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1083c4ccc6..f44f4fbca6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1071,6 +1071,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) { NetworkInfo info = getNetworkInfoForType(networkType); + return getFilteredNetworkInfo(info, networkType, uid); + } + + private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, int networkType, int uid) { if (isNetworkBlocked(networkType, uid)) { // network is blocked; clone and override state info = new NetworkInfo(info); @@ -1175,6 +1179,24 @@ public class ConnectivityService extends IConnectivityManager.Stub { return info; } + @Override + public NetworkInfo getNetworkInfoForNetwork(Network network) { + enforceAccessPermission(); + if (network == null) return null; + + final int uid = Binder.getCallingUid(); + NetworkAgentInfo nai = null; + synchronized (mNetworkForNetId) { + nai = mNetworkForNetId.get(network.netId); + } + if (nai == null) return null; + synchronized (nai) { + if (nai.networkInfo == null) return null; + + return getFilteredNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), uid); + } + } + @Override public NetworkInfo[] getAllNetworkInfo() { enforceAccessPermission(); @@ -1191,6 +1213,18 @@ public class ConnectivityService extends IConnectivityManager.Stub { return result.toArray(new NetworkInfo[result.size()]); } + @Override + public Network[] getAllNetworks() { + enforceAccessPermission(); + final ArrayList result = new ArrayList(); + synchronized (mNetworkForNetId) { + for (int i = 0; i < mNetworkForNetId.size(); i++) { + result.add(new Network(mNetworkForNetId.valueAt(i).network)); + } + } + return result.toArray(new Network[result.size()]); + } + @Override public boolean isNetworkSupported(int networkType) { enforceAccessPermission(); @@ -1223,16 +1257,31 @@ public class ConnectivityService extends IConnectivityManager.Stub { @Override public LinkProperties getLinkProperties(Network network) { enforceAccessPermission(); - NetworkAgentInfo nai = mNetworkForNetId.get(network.netId); - if (nai != null) return new LinkProperties(nai.linkProperties); + NetworkAgentInfo nai = null; + synchronized (mNetworkForNetId) { + nai = mNetworkForNetId.get(network.netId); + } + + if (nai != null) { + synchronized (nai) { + return new LinkProperties(nai.linkProperties); + } + } return null; } @Override public NetworkCapabilities getNetworkCapabilities(Network network) { enforceAccessPermission(); - NetworkAgentInfo nai = mNetworkForNetId.get(network.netId); - if (nai != null) return new NetworkCapabilities(nai.networkCapabilities); + NetworkAgentInfo nai = null; + synchronized (mNetworkForNetId) { + nai = mNetworkForNetId.get(network.netId); + } + if (nai != null) { + synchronized (nai) { + return new NetworkCapabilities(nai.networkCapabilities); + } + } return null; } @@ -1777,8 +1826,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { } return false; } - - DetailedState netState = nai.networkInfo.getDetailedState(); + DetailedState netState; + synchronized (nai) { + netState = nai.networkInfo.getDetailedState(); + } if ((netState != DetailedState.CONNECTED && netState != DetailedState.CAPTIVE_PORTAL_CHECK)) { @@ -1792,9 +1843,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - LinkProperties lp = nai.linkProperties; - boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, - nai.network.netId, uid); + LinkProperties lp = null; + int netId = INVALID_NET_ID; + synchronized (nai) { + lp = nai.linkProperties; + netId = nai.network.netId; + } + boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, netId, uid); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; } finally { @@ -3096,7 +3151,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { if (VDBG) log("Update of Linkproperties for " + nai.name()); LinkProperties oldLp = nai.linkProperties; - nai.linkProperties = (LinkProperties)msg.obj; + synchronized (nai) { + nai.linkProperties = (LinkProperties)msg.obj; + } updateLinkProperties(nai, oldLp); } break; @@ -3242,7 +3299,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { loge("Error connecting NetworkAgent"); NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo); if (nai != null) { - mNetworkForNetId.remove(nai.network.netId); + synchronized (mNetworkForNetId) { + mNetworkForNetId.remove(nai.network.netId); + } mLegacyTypeTracker.remove(nai); } } @@ -3275,7 +3334,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetworkAgentInfos.remove(msg.replyTo); updateClat(null, nai.linkProperties, nai); mLegacyTypeTracker.remove(nai); - mNetworkForNetId.remove(nai.network.netId); + synchronized (mNetworkForNetId) { + mNetworkForNetId.remove(nai.network.netId); + } // Since we've lost the network, go through all the requests that // it was satisfying and see if any other factory can satisfy them. final ArrayList toActivate = new ArrayList(); @@ -5565,7 +5626,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void handleRegisterNetworkAgent(NetworkAgentInfo na) { if (VDBG) log("Got NetworkAgent Messenger"); mNetworkAgentInfos.put(na.messenger, na); - mNetworkForNetId.put(na.network.netId, na); + synchronized (mNetworkForNetId) { + mNetworkForNetId.put(na.network.netId, na); + } na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger); NetworkInfo networkInfo = na.networkInfo; na.networkInfo = null; @@ -5710,7 +5773,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkCapabilities networkCapabilities) { // TODO - what else here? Verify still satisfies everybody? // Check if satisfies somebody new? call callbacks? - networkAgent.networkCapabilities = networkCapabilities; + synchronized (networkAgent) { + networkAgent.networkCapabilities = networkCapabilities; + } } private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) { @@ -5924,8 +5989,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) { NetworkInfo.State state = newInfo.getState(); - NetworkInfo oldInfo = networkAgent.networkInfo; - networkAgent.networkInfo = newInfo; + NetworkInfo oldInfo = null; + synchronized (networkAgent) { + oldInfo = networkAgent.networkInfo; + networkAgent.networkInfo = newInfo; + } if (oldInfo != null && oldInfo.getState() == state) { if (VDBG) log("ignoring duplicate network state non-change"); @@ -6054,9 +6122,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { private LinkProperties getLinkPropertiesForTypeInternal(int networkType) { NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - return (nai != null) ? - new LinkProperties(nai.linkProperties) : - new LinkProperties(); + if (nai != null) { + synchronized (nai) { + return new LinkProperties(nai.linkProperties); + } + } + return new LinkProperties(); } private NetworkInfo getNetworkInfoForType(int networkType) { @@ -6075,8 +6146,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { private NetworkCapabilities getNetworkCapabilitiesForType(int networkType) { NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); - return (nai != null) ? - new NetworkCapabilities(nai.networkCapabilities) : - new NetworkCapabilities(); + if (nai != null) { + synchronized (nai) { + return new NetworkCapabilities(nai.networkCapabilities); + } + } + return new NetworkCapabilities(); } }