diff options
author | Chalard Jean <jchalard@google.com> | 2019-12-01 21:26:44 -0800 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-12-01 21:26:44 -0800 |
commit | f477d5c4c6015cc7a4afdf741527eaf588b0eec7 (patch) | |
tree | 70b41d7a3180ac28ae54e7f033ee77bf00efac2b | |
parent | f1960474b1df233849c75d23c61b278e857e9459 (diff) | |
parent | 5cf5b30990cd33dc59a4e99559e8fc2ee2dcc11c (diff) | |
download | base-f477d5c4c6015cc7a4afdf741527eaf588b0eec7.tar.gz |
Merge changes I0613c23f,Ibeab8d0a,I8bd668ad,I7d3a16be
am: 5cf5b30990
Change-Id: Ibe34e78e53a15e987042703fdd27d6393e4e7d59
-rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 122 | ||||
-rw-r--r-- | tests/net/java/com/android/server/ConnectivityServiceTest.java | 53 |
2 files changed, 111 insertions, 64 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 652dd40297b9..36f44e48b877 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -925,6 +925,10 @@ public class ConnectivityService extends IConnectivityManager.Stub return IIpConnectivityMetrics.Stub.asInterface( ServiceManager.getService(IpConnectivityLog.SERVICE_NAME)); } + + public IBatteryStats getBatteryStatsService() { + return BatteryStatsService.getService(); + } } public ConnectivityService(Context context, INetworkManagementService netManager, @@ -2144,7 +2148,7 @@ public class ConnectivityService extends IConnectivityManager.Stub opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M); options = opts.toBundle(); } - final IBatteryStats bs = BatteryStatsService.getService(); + final IBatteryStats bs = mDeps.getBatteryStatsService(); try { bs.noteConnectivityChanged(intent.getIntExtra( ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE), @@ -5628,7 +5632,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // are accurate. networkAgent.clatd.fixupLinkProperties(oldLp, newLp); - updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities); + updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities, + networkAgent.networkInfo.getType()); // update filtering rules, need to happen after the interface update so netd knows about the // new interface (the interface name -> index map becomes initialized) @@ -5707,21 +5712,26 @@ public class ConnectivityService extends IConnectivityManager.Stub } - private void updateInterfaces(LinkProperties newLp, LinkProperties oldLp, int netId, - NetworkCapabilities caps) { - CompareResult<String> interfaceDiff = new CompareResult<>( + private void updateInterfaces(final @Nullable LinkProperties newLp, + final @Nullable LinkProperties oldLp, final int netId, + final @Nullable NetworkCapabilities caps, final int legacyType) { + final CompareResult<String> interfaceDiff = new CompareResult<>( oldLp != null ? oldLp.getAllInterfaceNames() : null, newLp != null ? newLp.getAllInterfaceNames() : null); - for (String iface : interfaceDiff.added) { - try { - if (DBG) log("Adding iface " + iface + " to network " + netId); - mNMS.addInterfaceToNetwork(iface, netId); - wakeupModifyInterface(iface, caps, true); - } catch (Exception e) { - loge("Exception adding interface: " + e); + if (!interfaceDiff.added.isEmpty()) { + final IBatteryStats bs = mDeps.getBatteryStatsService(); + for (final String iface : interfaceDiff.added) { + try { + if (DBG) log("Adding iface " + iface + " to network " + netId); + mNMS.addInterfaceToNetwork(iface, netId); + wakeupModifyInterface(iface, caps, true); + bs.noteNetworkInterfaceType(iface, legacyType); + } catch (Exception e) { + loge("Exception adding interface: " + e); + } } } - for (String iface : interfaceDiff.removed) { + for (final String iface : interfaceDiff.removed) { try { if (DBG) log("Removing iface " + iface + " from network " + netId); wakeupModifyInterface(iface, caps, false); @@ -6480,54 +6490,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork); notifyLockdownVpn(newNetwork); } - - if (reassignedRequests.containsValue(newNetwork) || newNetwork.isVPN()) { - // Notify battery stats service about this network, both the normal - // interface and any stacked links. - // TODO: Avoid redoing this; this must only be done once when a network comes online. - try { - final IBatteryStats bs = BatteryStatsService.getService(); - final int type = newNetwork.networkInfo.getType(); - - final String baseIface = newNetwork.linkProperties.getInterfaceName(); - bs.noteNetworkInterfaceType(baseIface, type); - for (LinkProperties stacked : newNetwork.linkProperties.getStackedLinks()) { - final String stackedIface = stacked.getInterfaceName(); - bs.noteNetworkInterfaceType(stackedIface, type); - } - } catch (RemoteException ignored) { - } - - // This has to happen after the notifyNetworkCallbacks as that tickles each - // ConnectivityManager instance so that legacy requests correctly bind dns - // requests to this network. The legacy users are listening for this broadcast - // and will generally do a dns request so they can ensureRouteToHost and if - // they do that before the callbacks happen they'll use the default network. - // - // TODO: Is there still a race here? We send the broadcast - // after sending the callback, but if the app can receive the - // broadcast before the callback, it might still break. - // - // This *does* introduce a race where if the user uses the new api - // (notification callbacks) and then uses the old api (getNetworkInfo(type)) - // they may get old info. Reverse this after the old startUsing api is removed. - // This is on top of the multiple intent sequencing referenced in the todo above. - for (int i = 0; i < newNetwork.numNetworkRequests(); i++) { - NetworkRequest nr = newNetwork.requestAt(i); - if (nr.legacyType != TYPE_NONE && nr.isRequest()) { - // legacy type tracker filters out repeat adds - mLegacyTypeTracker.add(nr.legacyType, newNetwork); - } - } - - // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above, - // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest - // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the - // newNetwork to the tracker explicitly (it's a no-op if it has already been added). - if (newNetwork.isVPN()) { - mLegacyTypeTracker.add(TYPE_VPN, newNetwork); - } - } } /** @@ -6550,6 +6512,26 @@ public class ConnectivityService extends IConnectivityManager.Stub for (NetworkAgentInfo nai : nais) { rematchNetworkAndRequests(nai, now); } + + // Now that all the callbacks have been sent, send the legacy network broadcasts + // as needed. This is necessary so that legacy requests correctly bind dns + // requests to this network. The legacy users are listening for this broadcast + // and will generally do a dns request so they can ensureRouteToHost and if + // they do that before the callbacks happen they'll use the default network. + // + // TODO: Is there still a race here? The legacy broadcast will be sent after sending + // callbacks, but if apps can receive the broadcast before the callback, they still might + // have an inconsistent view of networking. + // + // This *does* introduce a race where if the user uses the new api + // (notification callbacks) and then uses the old api (getNetworkInfo(type)) + // they may get old info. Reverse this after the old startUsing api is removed. + // This is on top of the multiple intent sequencing referenced in the todo above. + for (NetworkAgentInfo nai : nais) { + addNetworkToLegacyTypeTracker(nai); + } + + // Tear down all unneeded networks. for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { if (unneeded(nai, UnneededFor.TEARDOWN)) { if (nai.getLingerExpiry() > 0) { @@ -6569,6 +6551,24 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void addNetworkToLegacyTypeTracker(@NonNull final NetworkAgentInfo nai) { + for (int i = 0; i < nai.numNetworkRequests(); i++) { + NetworkRequest nr = nai.requestAt(i); + if (nr.legacyType != TYPE_NONE && nr.isRequest()) { + // legacy type tracker filters out repeat adds + mLegacyTypeTracker.add(nr.legacyType, nai); + } + } + + // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above, + // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest + // wants the NOT_VPN capability, so it will never be satisfied by a VPN). So, add the + // newNetwork to the tracker explicitly (it's a no-op if it has already been added). + if (nai.isVPN()) { + mLegacyTypeTracker.add(TYPE_VPN, nai); + } + } + private void updateInetCondition(NetworkAgentInfo nai) { // Don't bother updating until we've graduated to validated at least once. if (!nai.everValidated) return; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2a09f647a46b..c4e353bdca55 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -96,6 +96,7 @@ import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.atLeastOnce; @@ -198,6 +199,7 @@ import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.app.IBatteryStats; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; @@ -305,6 +307,7 @@ public class ConnectivityServiceTest { @Mock DefaultNetworkMetrics mDefaultNetworkMetrics; @Mock INetworkManagementService mNetworkManagementService; @Mock INetworkStatsService mStatsService; + @Mock IBatteryStats mBatteryStatsService; @Mock INetworkPolicyManager mNpm; @Mock IDnsResolver mMockDnsResolver; @Mock INetd mMockNetd; @@ -1135,6 +1138,7 @@ public class ConnectivityServiceTest { doReturn(mMetricsService).when(deps).getMetricsLogger(); doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics(); + doReturn(mBatteryStatsService).when(deps).getBatteryStatsService(); doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE); doAnswer(inv -> { mPolicyTracker = new WrappedMultinetworkPolicyTracker( @@ -5640,6 +5644,36 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(defaultCallback); } + @Test + public final void testBatteryStatsNetworkType() throws Exception { + final LinkProperties cellLp = new LinkProperties(); + cellLp.setInterfaceName("cell0"); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); + mCellNetworkAgent.connect(true); + waitForIdle(); + verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), + TYPE_MOBILE); + reset(mBatteryStatsService); + + final LinkProperties wifiLp = new LinkProperties(); + wifiLp.setInterfaceName("wifi0"); + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp); + mWiFiNetworkAgent.connect(true); + waitForIdle(); + verify(mBatteryStatsService).noteNetworkInterfaceType(wifiLp.getInterfaceName(), + TYPE_WIFI); + reset(mBatteryStatsService); + + mCellNetworkAgent.disconnect(); + + cellLp.setInterfaceName("wifi0"); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); + mCellNetworkAgent.connect(true); + waitForIdle(); + verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), + TYPE_MOBILE); + } + /** * Make simulated InterfaceConfig for Nat464Xlat to query clat lower layer info. */ @@ -5680,25 +5714,28 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(networkRequest, networkCallback); // Prepare ipv6 only link properties. - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - final int cellNetId = mCellNetworkAgent.getNetwork().netId; final LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); cellLp.addLinkAddress(myIpv6); cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME)); cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME)); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); reset(mNetworkManagementService); reset(mMockDnsResolver); reset(mMockNetd); + reset(mBatteryStatsService); when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) .thenReturn(getClatInterfaceConfig(myIpv4)); // Connect with ipv6 link properties. Expect prefix discovery to be started. - mCellNetworkAgent.sendLinkProperties(cellLp); mCellNetworkAgent.connect(true); + final int cellNetId = mCellNetworkAgent.getNetwork().netId; + waitForIdle(); verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); + verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), + TYPE_MOBILE); networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); @@ -5714,6 +5751,11 @@ public class ConnectivityServiceTest { verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); + // Make sure BatteryStats was not told about any v4- interfaces, as none should have + // come online yet. + waitForIdle(); + verify(mBatteryStatsService, never()).noteNetworkInterfaceType(startsWith("v4-"), anyInt()); + verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); reset(mMockNetd); @@ -5760,6 +5802,11 @@ public class ConnectivityServiceTest { assertEquals(1, resolvrParams.servers.length); assertTrue(ArrayUtils.contains(resolvrParams.servers, "8.8.8.8")); + for (final LinkProperties stackedLp : stackedLpsAfterChange) { + verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(), + TYPE_MOBILE); + } + // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. cellLp.addLinkAddress(myIpv4); |