From 20689682e5ea60514172b7c3c065e0720307d900 Mon Sep 17 00:00:00 2001 From: lifr Date: Wed, 12 Jan 2022 00:54:40 +0800 Subject: [PATCH] [DU03-1]Remove INetworkStatsService from BatteryStatsImpl Expose systemapi NetworkStats.getDetailedUidStats for use by BatteryStats. BatteryStatsImpl is using INetworkStatsService APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 210066922 Test: atest BatteryStatsImplTest WifiPowerCalculatorTest MobileRadioPowerCalculatorTest NetworkStatsServiceTest CTS-Coverage-Bug: 213437796 Change-Id: I40d713923278f4654d67bb4d12155cea85c10447 --- core/api/system-current.txt | 2 + .../android/internal/os/BatteryStatsImpl.java | 24 ++++----- .../internal/os/MockBatteryStatsImpl.java | 10 +++- .../app/usage/NetworkStatsManager.java | 52 ++++++++++++++----- .../src/android/net/INetworkStatsService.aidl | 10 +--- .../server/net/NetworkStatsService.java | 25 ++++++++- 6 files changed, 84 insertions(+), 39 deletions(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 3f7fc3fde2878..d19f717935d11 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1850,6 +1850,8 @@ package android.app.usage { } public class NetworkStatsManager { + method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats(); + method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 270b5d6903b59..8e9877e3cc1fc 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -136,9 +136,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Queue; -import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; @@ -11541,13 +11539,15 @@ public class BatteryStatsImpl extends BatteryStats { private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1); @VisibleForTesting - protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, - String[] ifaces) { - Objects.requireNonNull(networkStatsManager); - if (!ArrayUtils.isEmpty(ifaces)) { - return networkStatsManager.getDetailedUidStats(Set.of(ifaces)); - } - return null; + protected NetworkStats readMobileNetworkStatsLocked( + @NonNull NetworkStatsManager networkStatsManager) { + return networkStatsManager.getMobileUidStats(); + } + + @VisibleForTesting + protected NetworkStats readWifiNetworkStatsLocked( + @NonNull NetworkStatsManager networkStatsManager) { + return networkStatsManager.getWifiUidStats(); } /** @@ -11564,8 +11564,7 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mWifiNetworkLock) { - final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, - mWifiIfaces); + final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null, mNetworkStatsPool.acquire()); @@ -11932,8 +11931,7 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mModemNetworkLock) { - final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, - mModemIfaces); + final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null, mNetworkStatsPool.acquire()); diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java index db0c934bd0d4e..8b14c62dd1d70 100644 --- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java @@ -40,6 +40,7 @@ import java.util.concurrent.Future; public class MockBatteryStatsImpl extends BatteryStatsImpl { public BatteryStatsImpl.Clocks clocks; public boolean mForceOnBattery; + // The mNetworkStats will be used for both wifi and mobile categories private NetworkStats mNetworkStats; MockBatteryStatsImpl(Clocks clocks) { @@ -107,11 +108,16 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { } @Override - protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, - String[] ifaces) { + protected NetworkStats readMobileNetworkStatsLocked( + @NonNull NetworkStatsManager networkStatsManager) { return mNetworkStats; } + @Override + protected NetworkStats readWifiNetworkStatsLocked( + @NonNull NetworkStatsManager networkStatsManager) { + return mNetworkStats; + } public MockBatteryStatsImpl setPowerProfile(PowerProfile powerProfile) { mPowerProfile = powerProfile; return this; diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java index 8d93354ea9d7c..683678ad46714 100644 --- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -17,6 +17,8 @@ package android.app.usage; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; import android.annotation.NonNull; @@ -55,7 +57,6 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; -import java.util.Set; /** * Provides access to network usage history and statistics. Usage data is collected in @@ -670,26 +671,49 @@ public class NetworkStatsManager { } /** - * Query realtime network usage statistics details with interfaces constrains. - * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING}, - * video calling data usage and count of network operations that set by - * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any - * statistics that is reported by {@link NetworkStatsProvider}. + * Query realtime mobile network usage statistics. * - * @param requiredIfaces A list of interfaces the stats should be restricted to, or - * {@link NetworkStats#INTERFACES_ALL}. + * Return a snapshot of current UID network statistics, as it applies + * to the mobile radios of the device. The snapshot will include any + * tethering traffic, video calling data usage and count of + * network operations set by {@link TrafficStats#incrementOperationCount} + * made over a mobile radio. + * The snapshot will not include any statistics that cannot be seen by + * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s. * * @hide */ - //@SystemApi + @SystemApi @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - @NonNull public android.net.NetworkStats getDetailedUidStats( - @NonNull Set requiredIfaces) { - Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null"); + @NonNull public android.net.NetworkStats getMobileUidStats() { try { - return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0])); + return mService.getUidStatsForTransport(TRANSPORT_CELLULAR); } catch (RemoteException e) { - if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats"); + if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats"); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Query realtime Wi-Fi network usage statistics. + * + * Return a snapshot of current UID network statistics, as it applies + * to the Wi-Fi radios of the device. The snapshot will include any + * tethering traffic, video calling data usage and count of + * network operations set by {@link TrafficStats#incrementOperationCount} + * made over a Wi-Fi radio. + * The snapshot will not include any statistics that cannot be seen by + * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s. + * + * @hide + */ + @SystemApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + @NonNull public android.net.NetworkStats getWifiUidStats() { + try { + return mService.getUidStatsForTransport(TRANSPORT_WIFI); + } catch (RemoteException e) { + if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats"); throw e.rethrowFromSystemServer(); } } diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl index a4babb543dbdb..da0aa99b9370b 100644 --- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl +++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl @@ -49,14 +49,8 @@ interface INetworkStatsService { @UnsupportedAppUsage NetworkStats getDataLayerSnapshotForUid(int uid); - /** Get a detailed snapshot of stats since boot for all UIDs. - * - *

Results will not always be limited to stats on requiredIfaces when specified: stats for - * interfaces stacked on the specified interfaces, or for interfaces on which the specified - * interfaces are stacked on, will also be included. - * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}. - */ - NetworkStats getDetailedUidStats(in String[] requiredIfaces); + /** Get the transport NetworkStats for all UIDs since boot. */ + NetworkStats getUidStatsForTransport(int transport); /** Return set of any ifaces associated with mobile networks since boot. */ @UnsupportedAppUsage diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java index 8e15f799c3123..192c5c12975eb 100644 --- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java +++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java @@ -28,6 +28,7 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_VT; @@ -291,6 +292,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Set of any ifaces associated with mobile networks since boot. */ private volatile String[] mMobileIfaces = new String[0]; + /** Set of any ifaces associated with wifi networks since boot. */ + private volatile String[] mWifiIfaces = new String[0]; + /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; @@ -1005,11 +1009,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public NetworkStats getDetailedUidStats(String[] requiredIfaces) { + public NetworkStats getUidStatsForTransport(int transport) { enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); try { + final String[] relevantIfaces = + transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces; + // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked + // interfaces, so this is not useful, remove it. final String[] ifacesToQuery = - mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); + mStatsFactory.augmentWithStackedInterfaces(relevantIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); @@ -1368,10 +1376,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); + final ArraySet wifiIfaces = new ArraySet<>(); for (NetworkStateSnapshot snapshot : snapshots) { final int displayTransport = getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); + final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport); final boolean isDefault = CollectionUtils.contains( mDefaultNetworks, snapshot.getNetwork()); final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL @@ -1407,6 +1417,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(baseIface); } + if (isWifi) { + wifiIfaces.add(baseIface); + } } // Traffic occurring on stacked interfaces is usually clatd. @@ -1448,6 +1461,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(iface); } + if (isWifi) { + wifiIfaces.add(iface); + } mStatsFactory.noteStackedIface(iface, baseIface); } @@ -1455,11 +1471,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mMobileIfaces = mobileIfaces.toArray(new String[0]); + mWifiIfaces = wifiIfaces.toArray(new String[0]); // TODO (b/192758557): Remove debug log. if (CollectionUtils.contains(mMobileIfaces, null)) { throw new NullPointerException( "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); } + if (CollectionUtils.contains(mWifiIfaces, null)) { + throw new NullPointerException( + "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces)); + } } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {