From 0f0a7c52e18ab8631450d939f8d5aea8724d55e7 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Wed, 21 May 2014 20:04:36 -0700 Subject: [PATCH 1/8] Move dis/enable of mobile data to Telephony ConnectivityService doesn't do this anymore. bug:15077247 Change-Id: I3208c91b2c0369b594987f39ca29da7478435513 --- .../java/android/net/ConnectivityManager.java | 38 ++++++----------- .../android/net/IConnectivityManager.aidl | 3 -- .../android/server/ConnectivityService.java | 41 ------------------- 3 files changed, 12 insertions(+), 70 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 80a9598ada..2f2aba3286 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -35,15 +35,17 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; +import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.telephony.ITelephony; +import com.android.internal.util.Protocol; + import java.net.InetAddress; import java.util.concurrent.atomic.AtomicInteger; import java.util.HashMap; -import com.android.internal.util.Protocol; - /** * Class that answers queries about the state of network connectivity. It also * notifies applications when network connectivity changes. Get an instance @@ -940,34 +942,18 @@ public class ConnectivityManager { } /** - * Gets the value of the setting for enabling Mobile data. - * - * @return Whether mobile data is enabled. - * - *

This method requires the call to hold the permission - * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @hide + * @deprecated Talk to TelephonyManager directly */ public boolean getMobileDataEnabled() { - try { - return mService.getMobileDataEnabled(); - } catch (RemoteException e) { - return true; - } - } - - /** - * Sets the persisted value for enabling/disabling Mobile data. - * - * @param enabled Whether the user wants the mobile data connection used - * or not. - * @hide - */ - public void setMobileDataEnabled(boolean enabled) { - try { - mService.setMobileDataEnabled(enabled); - } catch (RemoteException e) { + IBinder b = ServiceManager.getService(Context.TELEPHONY_SERVICE); + if (b != null) { + try { + ITelephony it = ITelephony.Stub.asInterface(b); + return it.getDataEnabled(); + } catch (RemoteException e) { } } + return false; } /** diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index d97b1e95bd..baec36ad48 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -74,9 +74,6 @@ interface IConnectivityManager boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, String packageName); - boolean getMobileDataEnabled(); - void setMobileDataEnabled(boolean enabled); - /** Policy control over specific {@link NetworkStateTracker}. */ void setPolicyDataEnable(int networkType, boolean enabled); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0ad5ce269a..37b75d6877 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -342,12 +342,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private static final int EVENT_INET_CONDITION_HOLD_END = 5; - /** - * used internally to set enable/disable cellular data - * arg1 = ENBALED or DISABLED - */ - private static final int EVENT_SET_MOBILE_DATA = 7; - /** * used internally to clear a wakelock when transitioning * from one net to another @@ -1822,20 +1816,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { return true; } - /** - * @see ConnectivityManager#getMobileDataEnabled() - */ - public boolean getMobileDataEnabled() { - // TODO: This detail should probably be in DataConnectionTracker's - // which is where we store the value and maybe make this - // asynchronous. - enforceAccessPermission(); - boolean retVal = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.MOBILE_DATA, 1) == 1; - if (VDBG) log("getMobileDataEnabled returning " + retVal); - return retVal; - } - public void setDataDependency(int networkType, boolean met) { enforceConnectivityInternalPermission(); @@ -1908,22 +1888,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } }; - /** - * @see ConnectivityManager#setMobileDataEnabled(boolean) - */ - public void setMobileDataEnabled(boolean enabled) { - enforceChangePermission(); - if (DBG) log("setMobileDataEnabled(" + enabled + ")"); - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA, - (enabled ? ENABLED : DISABLED), 0)); - } - - private void handleSetMobileData(boolean enabled) { - // TODO - handle this - probably generalize passing in a transport type and send to the - // factories? - } - @Override public void setPolicyDataEnable(int networkType, boolean enabled) { // only someone like NPMS should only be calling us @@ -3315,11 +3279,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { handleInetConditionHoldEnd(netType, sequence); break; } - case EVENT_SET_MOBILE_DATA: { - boolean enabled = (msg.arg1 == ENABLED); - handleSetMobileData(enabled); - break; - } case EVENT_APPLY_GLOBAL_HTTP_PROXY: { handleDeprecatedGlobalHttpProxy(); break; From b2754a0b098405130fe35b6e3872ef7b42af557d Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 21 May 2014 15:01:03 -0700 Subject: [PATCH 2/8] Battery monitoring fixes: - Improve monitoring of level changes to not be confused when it goes up while draining or down while charging. - Put back in connectivity service code to tell battery stats about the interfaces. - Turn back on reporting of mobile radio active state from the RIL. - Fix bug in marshalling/unmarshalling that would cause the UI to show bad data. Change-Id: I733ef52702894cca81a0813eccdfc1023e546fce --- .../java/com/android/server/ConnectivityService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 37b75d6877..1e21e1cc51 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5709,10 +5709,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { // updateNetworkSettings(); } // notify battery stats service about this network -// try { - // TODO - //BatteryStatsService.getService().noteNetworkInterfaceType(iface, netType); -// } catch (RemoteException e) { } + try { + BatteryStatsService.getService().noteNetworkInterfaceType( + newNetwork.linkProperties.getInterfaceName(), + newNetwork.networkInfo.getType()); + } catch (RemoteException e) { } notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE); } else { if (DBG && newNetwork.networkRequests.size() != 0) { From 1890801fc35e9d7340dcce7677ec20c447a8bf4f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 29 May 2014 14:05:41 +0900 Subject: [PATCH 3/8] Don't break things if a network goes back to CONNECTED. Currently, if a network goes from CONNECTED to some other "live" state (e.g., CONNECTING, because it's VERIFYING_POOR_LINK) and back, ConnectivityService treats it as if a new network had connected. This causes it to attempt to create the network (which fails, since a network with that netid already exists), to trigger verification, and if the verification succeeds, to tear down the network because the request it's satisfying is already satisfied by the network itself. Instead, if creating the network fails, assume it's because the network had already been created, and bail out. Also, when validation completes, ignore NetworkRequests that were being served by the same NetworkAgent as before. Bug: 15244052 Change-Id: Ifd73558e5be452d9ef88c64cca429d5f302bf354 --- .../android/server/ConnectivityService.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1e21e1cc51..5527528fd2 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5606,16 +5606,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { boolean isNewDefault = false; if (DBG) log("handleConnectionValidated for "+newNetwork.name()); // check if any NetworkRequest wants this NetworkAgent - // first check if it satisfies the NetworkCapabilities ArrayList affectedNetworks = new ArrayList(); if (VDBG) log(" new Network has: " + newNetwork.networkCapabilities); for (NetworkRequestInfo nri : mNetworkRequests.values()) { + NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId); + if (newNetwork == currentNetwork) { + if (VDBG) log("Network " + newNetwork.name() + " was already satisfying" + + " request " + nri.request.requestId + ". No change."); + keep = true; + continue; + } + + // check if it satisfies the NetworkCapabilities if (VDBG) log(" checking if request is satisfied: " + nri.request); if (nri.request.networkCapabilities.satisfiedByNetworkCapabilities( newNetwork.networkCapabilities)) { // next check if it's better than any current network we're using for // this request - NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId); if (VDBG) { log("currentScore = " + (currentNetwork != null ? currentNetwork.currentScore : 0) + @@ -5744,12 +5751,19 @@ public class ConnectivityService extends IConnectivityManager.Stub { } if (state == NetworkInfo.State.CONNECTED) { - // TODO - check if we want it (optimization) try { + // This is likely caused by the fact that this network already + // exists. An example is when a network goes from CONNECTED to + // CONNECTING and back (like wifi on DHCP renew). + // TODO: keep track of which networks we've created, or ask netd + // to tell us whether we've already created this network or not. mNetd.createNetwork(networkAgent.network.netId); } catch (Exception e) { - loge("Error creating Network " + networkAgent.network.netId); + loge("Error creating network " + networkAgent.network.netId + ": " + + e.getMessage()); + return; } + updateLinkProperties(networkAgent, null); notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK); networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED); From c00a3f110ccc15d6b8c4af2abf0d7c974dd85f11 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Tue, 3 Jun 2014 17:22:11 -0700 Subject: [PATCH 4/8] Fix legacy APIs. Two fixes. First make sure we mark the request as handled by the network handling it. Second, convert ensureRouteToHostForAddress to use the new legacyNetworkForType. bug:14993207 Change-Id: I230968938ca0ed91f834b36a2af60caff2eab682 --- .../android/server/ConnectivityService.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b2b4217140..abb8cc5e25 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1754,31 +1754,34 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType); return false; } - NetworkStateTracker tracker = mNetTrackers[networkType]; - DetailedState netState = DetailedState.DISCONNECTED; - if (tracker != null) { - netState = tracker.getNetworkInfo().getDetailedState(); + + NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); + if (nai == null) { + if (mLegacyTypeTracker.isTypeSupported(networkType) == false) { + if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType); + } else { + if (DBG) log("requestRouteToHostAddress on down network: " + networkType); + } + return false; } + DetailedState netState = nai.networkInfo.getDetailedState(); + if ((netState != DetailedState.CONNECTED && - netState != DetailedState.CAPTIVE_PORTAL_CHECK) || - tracker.isTeardownRequested()) { + netState != DetailedState.CAPTIVE_PORTAL_CHECK)) { if (VDBG) { log("requestRouteToHostAddress on down network " + "(" + networkType + ") - dropped" - + " tracker=" + tracker - + " netState=" + netState - + " isTeardownRequested=" - + ((tracker != null) ? tracker.isTeardownRequested() : "tracker:null")); + + " netState=" + netState); } return false; } final int uid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); try { - LinkProperties lp = tracker.getLinkProperties(); + LinkProperties lp = nai.linkProperties; boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt, - tracker.getNetwork().netId, uid); + nai.network.netId, uid); if (DBG) log("requestRouteToHostAddress ok=" + ok); return ok; } finally { @@ -3316,6 +3319,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (bestNetwork != null) { if (VDBG) log("using " + bestNetwork.name()); bestNetwork.addRequest(nri.request); + mNetworkForRequestId.put(nri.request.requestId, bestNetwork); int legacyType = nri.request.legacyType; if (legacyType != TYPE_NONE) { mLegacyTypeTracker.add(legacyType, bestNetwork); From 4e2f3b1df96394e0b92d1c45921953d018ff3b2d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 4 Jun 2014 12:20:06 +0900 Subject: [PATCH 5/8] Make requests for restricted networks not require unrestricted access. Currently, calling startUsingNetworkFeature for a restricted APN type (e.g., IMS or FOTA) will create a request that requires NET_CAPABILITY_NOT_RESTRICTED. Because these APNs are restricted, when we bring them up we conclude that it does not match the unrestricted requirement, and we tear them down. 1. Clear the NET_CAPABILITY_NOT_RESTRICTED capability when creating requests in startUsingNetworkFeature. 2. Refactor the code to a common function so this cannot happen again. Bug: 15191336 Change-Id: Id1ec79c58ff79b1a83457ffaecc57d50b61ed4e4 --- .../java/android/net/ConnectivityManager.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a48a388820..c4cbdd54d2 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -870,6 +870,26 @@ public class ConnectivityManager { return 1; } + /** + * Removes the NET_CAPABILITY_NOT_RESTRICTED capability from the given + * NetworkCapabilities object if it lists any capabilities that are + * typically provided by retricted networks. + * @hide + */ + public static void maybeMarkCapabilitiesRestricted(NetworkCapabilities nc) { + for (Integer capability: nc.getNetworkCapabilities()) { + switch (capability.intValue()) { + case NetworkCapabilities.NET_CAPABILITY_CBS: + case NetworkCapabilities.NET_CAPABILITY_DUN: + case NetworkCapabilities.NET_CAPABILITY_FOTA: + case NetworkCapabilities.NET_CAPABILITY_IA: + case NetworkCapabilities.NET_CAPABILITY_IMS: + nc.removeNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + break; + } + } + } + private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { if (networkType == TYPE_MOBILE) { int cap = -1; @@ -893,12 +913,14 @@ public class ConnectivityManager { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); netCap.addNetworkCapability(cap); + maybeMarkCapabilitiesRestricted(netCap); return netCap; } else if (networkType == TYPE_WIFI) { if ("p2p".equals(feature)) { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P); + maybeMarkCapabilitiesRestricted(netCap); return netCap; } } From f7208e9857e41612141fcfa153b5af2dff4bd528 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 4 Jun 2014 19:59:21 +0900 Subject: [PATCH 6/8] Call a network restricted only if all capabilities are restricted When guessing whether a network is restricted or not (e.g., when constructing a NetworkCapabilities object from an APN type, or when constructing a request using startUsingNetworkFeature), only assume the network is restricted if all the capabilities it provides are typically provided by restricted networks (e.g., IMS, FOTA, etc.). Previous code would conclude a network was restricted even if it supported one "restricted" capability, so for example an APN that provides both Internet connectivity and FOTA was marked as restricted. This caused it to become ineligible to provide the default Internet connection, because that must be unrestricted. Also expand the list of restricted APN types a bit. Bug: 15417453 Change-Id: I8c385f2cc83c695449dc8cf943d918321716fe58 --- .../java/android/net/ConnectivityManager.java | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index c4cbdd54d2..b96f16646c 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -872,22 +872,36 @@ public class ConnectivityManager { /** * Removes the NET_CAPABILITY_NOT_RESTRICTED capability from the given - * NetworkCapabilities object if it lists any capabilities that are - * typically provided by retricted networks. + * NetworkCapabilities object if all the capabilities it provides are + * typically provided by restricted networks. + * + * TODO: consider: + * - Moving to NetworkCapabilities + * - Renaming it to guessRestrictedCapability and make it set the + * restricted capability bit in addition to clearing it. * @hide */ public static void maybeMarkCapabilitiesRestricted(NetworkCapabilities nc) { - for (Integer capability: nc.getNetworkCapabilities()) { + for (Integer capability : nc.getNetworkCapabilities()) { switch (capability.intValue()) { case NetworkCapabilities.NET_CAPABILITY_CBS: case NetworkCapabilities.NET_CAPABILITY_DUN: + case NetworkCapabilities.NET_CAPABILITY_EIMS: case NetworkCapabilities.NET_CAPABILITY_FOTA: case NetworkCapabilities.NET_CAPABILITY_IA: case NetworkCapabilities.NET_CAPABILITY_IMS: - nc.removeNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - break; + case NetworkCapabilities.NET_CAPABILITY_RCS: + case NetworkCapabilities.NET_CAPABILITY_XCAP: + continue; + default: + // At least one capability usually provided by unrestricted + // networks. Conclude that this network is unrestricted. + return; } } + // All the capabilities are typically provided by restricted networks. + // Conclude that this network is restricted. + nc.removeNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { From 97b48c282b7204abfc10ee81e9f1f44f9a708db6 Mon Sep 17 00:00:00 2001 From: Sreeram Ramachandran Date: Wed, 11 Jun 2014 15:56:51 -0700 Subject: [PATCH 7/8] Fix wifi connectivity issues. http://ag/480881 changed RouteInfo.getDestination() to return an IpPrefix instead of a LinkAddress. This makes the equals() comparison always fail. So, when ConnectivityService.updateRoutes() is given identical routes, instead of realizing that there's no diff, it would consider them different, and thus add and remove the same route. The add would fail, since the route already existed in netd, but the remove would succeed, leaving the system with no routes and thus no connectivity. Bug: 15564210 Change-Id: I2003b0fcb809cc20837dc489c58af37891ca4556 --- core/java/android/net/RouteInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index af27e1ddd1..8b42bcd5cb 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -361,7 +361,7 @@ public class RouteInfo implements Parcelable { RouteInfo target = (RouteInfo) obj; - return Objects.equals(mDestination, target.getDestination()) && + return Objects.equals(mDestination, target.getDestinationLinkAddress()) && Objects.equals(mGateway, target.getGateway()) && Objects.equals(mInterface, target.getInterface()); } From 8729530aa0a2560b1e6f00a362bce4e4fc4650b3 Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Wed, 2 Jul 2014 12:02:59 -0400 Subject: [PATCH 8/8] When adding a NetworkRequest, cancel linger for satisfying Network. This fixes a problem where a requested network can later suddenly disappear if it was lingering when the request arrived and later the linger timeout expired. bug:15927234 Change-Id: Ib3fae45820ce4421e3bc5b623937a16d5f1efa0f --- .../core/java/com/android/server/ConnectivityService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 87d28d35a2..bce2800f45 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3332,6 +3332,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } if (bestNetwork != null) { if (VDBG) log("using " + bestNetwork.name()); + if (nri.isRequest && bestNetwork.networkInfo.isConnected()) { + // Cancel any lingering so the linger timeout doesn't teardown this network + // even though we have a request for it. + bestNetwork.networkLingered.clear(); + bestNetwork.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED); + } bestNetwork.addRequest(nri.request); mNetworkForRequestId.put(nri.request.requestId, bestNetwork); int legacyType = nri.request.legacyType;