Loading services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +101 −118 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.server.stats.pull; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE; import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; Loading Loading @@ -73,6 +70,7 @@ import android.app.ProcessMemoryState; import android.app.RuntimeAppOpAccessMessage; import android.app.StatsManager; import android.app.StatsManager.PullAtomMetadata; import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; import android.bluetooth.UidTraffic; Loading @@ -86,8 +84,6 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.net.ConnectivityManager; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkRequest; import android.net.NetworkStats; Loading Loading @@ -181,6 +177,7 @@ import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.net.module.util.NetworkStatsUtils; import com.android.role.RoleManagerLocal; import com.android.server.BinderCallsStatsService; import com.android.server.LocalManagerRegistry; Loading Loading @@ -228,7 +225,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.BiConsumer; import java.util.function.Function; /** * SystemService containing PullAtomCallbacks that are registered with statsd. Loading Loading @@ -324,6 +321,7 @@ public class StatsPullAtomService extends SystemService { private WifiManager mWifiManager; private TelephonyManager mTelephony; private SubscriptionManager mSubscriptionManager; private NetworkStatsManager mNetworkStatsManager; @GuardedBy("mKernelWakelockLock") private KernelWakelockReader mKernelWakelockReader; Loading Loading @@ -769,7 +767,7 @@ public class StatsPullAtomService extends SystemService { mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class); // Initialize DiskIO mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(); Loading Loading @@ -959,32 +957,6 @@ public class StatsPullAtomService extends SystemService { registerOemManagedBytesTransfer(); } /** * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or * null if the service or binder cannot be obtained. Calling this method will trigger poll * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit} * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at * the network usage of their app. */ @Nullable private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) { final INetworkStatsService networkStatsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); if (networkStatsService == null) return null; try { return networkStatsService.openSessionForUsageStats( FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE : FLAG_POLL_ON_OPEN), mContext.getOpPackageName()); } catch (RemoteException e) { Slog.e(TAG, "Cannot get NetworkStats session", e); return null; } } private IThermalService getIThermalService() { synchronized (mThermalLock) { if (mThermalService == null) { Loading Loading @@ -1115,8 +1087,8 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); } break; } Loading @@ -1132,7 +1104,7 @@ public class StatsPullAtomService extends SystemService { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false)); } break; Loading Loading @@ -1223,23 +1195,19 @@ public class StatsPullAtomService extends SystemService { private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStatsExt statsExt) { int size = statsExt.stats.size(); final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling for (int j = 0; j < size; j++) { statsExt.stats.getValues(j, entry); for (NetworkStats.Entry entry : statsExt.stats) { StatsEvent statsEvent; if (statsExt.slicedByFgbg) { // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom. statsEvent = FrameworkStatsLog.buildStatsEvent( atomTag, entry.uid, (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets); atomTag, entry.getUid(), (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()); } else { // MobileBytesTransfer atom or WifiBytesTransfer atom. statsEvent = FrameworkStatsLog.buildStatsEvent( atomTag, entry.uid, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets); atomTag, entry.getUid(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()); } ret.add(statsEvent); } Loading @@ -1247,13 +1215,12 @@ public class StatsPullAtomService extends SystemService { private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid, entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets)); FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(), entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets())); } } Loading @@ -1268,12 +1235,11 @@ public class StatsPullAtomService extends SystemService { // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with. final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR; final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.getSet(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType, // Fill information about subscription, these cannot be null since invalid data // would be filtered when adding into subInfo list. Loading @@ -1287,15 +1253,13 @@ public class StatsPullAtomService extends SystemService { private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling final int oemManaged = statsExt.oemManaged; for (final int transport : statsExt.transports) { for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0), oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets)); FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(), (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets())); } } } Loading Loading @@ -1357,22 +1321,32 @@ public class StatsPullAtomService extends SystemService { final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(), NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS); try { // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats // history when query in every second in order to show realtime statistics. However, // this is not a good long-term solution since NetworkStatsService will make frequent // I/O and also block main thread when polling. // Consider making perfd queries NetworkStatsService directly. final NetworkStats stats = getNetworkStatsSession(template.getMatchRule() == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis, includeTags); return stats; } catch (RemoteException | NullPointerException e) { Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags=" + includeTags + " causes error", e); if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) { mNetworkStatsManager.forceUpdate(); } return null; final android.app.usage.NetworkStats queryNonTaggedStats = mNetworkStatsManager.querySummary( template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis); final NetworkStats nonTaggedStats = NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats); if (!includeTags) return nonTaggedStats; final android.app.usage.NetworkStats quaryTaggedStats = mNetworkStatsManager.queryTaggedSummary(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis); final NetworkStats taggedStats = NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats); return nonTaggedStats.add(taggedStats); } @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub( Loading @@ -1396,27 +1370,51 @@ public class StatsPullAtomService extends SystemService { return ret; } @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), NetworkStats.SET_ALL, NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.set = oldEntry.set; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL, entry.getSet(), NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.uid = oldEntry.uid; newEntry.set = oldEntry.set; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), entry.getSet(), NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.uid = oldEntry.uid; newEntry.tag = oldEntry.tag; newEntry.metered = oldEntry.metered; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), NetworkStats.SET_ALL, entry.getTag(), entry.getMetered(), NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } Loading @@ -1426,46 +1424,31 @@ public class StatsPullAtomService extends SystemService { * * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the * default state (with the presumption that we don't want to slice on anything), and then * applies the slicer lambda to allow users to control which dimensions to slice on. This is * adapted from groupedByUid within NetworkStats.java * applies the slicer lambda to allow users to control which dimensions to slice on. * * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old * NetworkStats.Entry, that should be used to copy state from the old to the new. * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to * get the state from entry to replace the default value. * This is useful for slicing by particular dimensions. For example, if we wished * to slice by uid and tag, we could write the following lambda: * (new, old) -> { * new.uid = old.uid; * new.tag = old.tag; * (entry) -> { * return new NetworkStats.Entry(null, entry.getUid(), * NetworkStats.SET_ALL, entry.getTag(), * NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, * NetworkStats.DEFAULT_NETWORK_ALL, * entry.getRxBytes(), entry.getRxPackets(), * entry.getTxBytes(), entry.getTxPackets(), 0); * } * If no slicer is provided, the data is not sliced by any dimensions. * @return new NeworkStats object appropriately sliced */ @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats, @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) { final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); final NetworkStats.Entry entry = new NetworkStats.Entry(); entry.uid = NetworkStats.UID_ALL; entry.iface = NetworkStats.IFACE_ALL; entry.set = NetworkStats.SET_ALL; entry.tag = NetworkStats.TAG_NONE; entry.metered = NetworkStats.METERED_ALL; entry.roaming = NetworkStats.ROAMING_ALL; entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL; final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values for (int i = 0; i < stats.size(); i++) { stats.getValues(i, recycle); @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) { NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); NetworkStats.Entry entry = new NetworkStats.Entry(); for (NetworkStats.Entry e : stats) { if (slicer != null) { slicer.accept(entry, recycle); entry = slicer.apply(e); } entry.rxBytes = recycle.rxBytes; entry.rxPackets = recycle.rxPackets; entry.txBytes = recycle.txBytes; entry.txPackets = recycle.txPackets; // Operations purposefully omitted since we don't use them for statsd. ret.combineValues(entry); ret = ret.addEntry(entry); } return ret; } Loading Loading
services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +101 −118 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.server.stats.pull; import static android.app.AppOpsManager.OP_FLAG_SELF; import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE; import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; Loading Loading @@ -73,6 +70,7 @@ import android.app.ProcessMemoryState; import android.app.RuntimeAppOpAccessMessage; import android.app.StatsManager; import android.app.StatsManager.PullAtomMetadata; import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; import android.bluetooth.UidTraffic; Loading @@ -86,8 +84,6 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.net.ConnectivityManager; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkRequest; import android.net.NetworkStats; Loading Loading @@ -181,6 +177,7 @@ import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.net.module.util.NetworkStatsUtils; import com.android.role.RoleManagerLocal; import com.android.server.BinderCallsStatsService; import com.android.server.LocalManagerRegistry; Loading Loading @@ -228,7 +225,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.BiConsumer; import java.util.function.Function; /** * SystemService containing PullAtomCallbacks that are registered with statsd. Loading Loading @@ -324,6 +321,7 @@ public class StatsPullAtomService extends SystemService { private WifiManager mWifiManager; private TelephonyManager mTelephony; private SubscriptionManager mSubscriptionManager; private NetworkStatsManager mNetworkStatsManager; @GuardedBy("mKernelWakelockLock") private KernelWakelockReader mKernelWakelockReader; Loading Loading @@ -769,7 +767,7 @@ public class StatsPullAtomService extends SystemService { mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class); // Initialize DiskIO mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(); Loading Loading @@ -959,32 +957,6 @@ public class StatsPullAtomService extends SystemService { registerOemManagedBytesTransfer(); } /** * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or * null if the service or binder cannot be obtained. Calling this method will trigger poll * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit} * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at * the network usage of their app. */ @Nullable private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) { final INetworkStatsService networkStatsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); if (networkStatsService == null) return null; try { return networkStatsService.openSessionForUsageStats( FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE : FLAG_POLL_ON_OPEN), mContext.getOpPackageName()); } catch (RemoteException e) { Slog.e(TAG, "Cannot get NetworkStats session", e); return null; } } private IThermalService getIThermalService() { synchronized (mThermalLock) { if (mThermalService == null) { Loading Loading @@ -1115,8 +1087,8 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false)); } break; } Loading @@ -1132,7 +1104,7 @@ public class StatsPullAtomService extends SystemService { final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR); if (stats != null) { ret.add(new NetworkStatsExt(stats.groupedByUid(), ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats), new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false)); } break; Loading Loading @@ -1223,23 +1195,19 @@ public class StatsPullAtomService extends SystemService { private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStatsExt statsExt) { int size = statsExt.stats.size(); final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling for (int j = 0; j < size; j++) { statsExt.stats.getValues(j, entry); for (NetworkStats.Entry entry : statsExt.stats) { StatsEvent statsEvent; if (statsExt.slicedByFgbg) { // MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom. statsEvent = FrameworkStatsLog.buildStatsEvent( atomTag, entry.uid, (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets); atomTag, entry.getUid(), (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()); } else { // MobileBytesTransfer atom or WifiBytesTransfer atom. statsEvent = FrameworkStatsLog.buildStatsEvent( atomTag, entry.uid, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets); atomTag, entry.getUid(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()); } ret.add(statsEvent); } Loading @@ -1247,13 +1215,12 @@ public class StatsPullAtomService extends SystemService { private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid, entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets)); FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(), entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets())); } } Loading @@ -1268,12 +1235,11 @@ public class StatsPullAtomService extends SystemService { // Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with. final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR; final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.getSet(), entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType, // Fill information about subscription, these cannot be null since invalid data // would be filtered when adding into subInfo list. Loading @@ -1287,15 +1253,13 @@ public class StatsPullAtomService extends SystemService { private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt, @NonNull List<StatsEvent> pulledData) { final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling final int oemManaged = statsExt.oemManaged; for (final int transport : statsExt.transports) { for (int i = 0; i < statsExt.stats.size(); i++) { statsExt.stats.getValues(i, entry); for (NetworkStats.Entry entry : statsExt.stats) { pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0), oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets)); FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(), (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets())); } } } Loading Loading @@ -1357,22 +1321,32 @@ public class StatsPullAtomService extends SystemService { final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(), NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS); try { // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats // history when query in every second in order to show realtime statistics. However, // this is not a good long-term solution since NetworkStatsService will make frequent // I/O and also block main thread when polling. // Consider making perfd queries NetworkStatsService directly. final NetworkStats stats = getNetworkStatsSession(template.getMatchRule() == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis, includeTags); return stats; } catch (RemoteException | NullPointerException e) { Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags=" + includeTags + " causes error", e); if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) { mNetworkStatsManager.forceUpdate(); } return null; final android.app.usage.NetworkStats queryNonTaggedStats = mNetworkStatsManager.querySummary( template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis); final NetworkStats nonTaggedStats = NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats); if (!includeTags) return nonTaggedStats; final android.app.usage.NetworkStats quaryTaggedStats = mNetworkStatsManager.queryTaggedSummary(template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis); final NetworkStats taggedStats = NetworkStatsUtils.fromPublicNetworkStats(quaryTaggedStats); return nonTaggedStats.add(taggedStats); } @NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub( Loading @@ -1396,27 +1370,51 @@ public class StatsPullAtomService extends SystemService { return ret; } @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), NetworkStats.SET_ALL, NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.set = oldEntry.set; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL, entry.getSet(), NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.uid = oldEntry.uid; newEntry.set = oldEntry.set; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), entry.getSet(), NetworkStats.TAG_NONE, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } @NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) { return sliceNetworkStats(stats, (newEntry, oldEntry) -> { newEntry.uid = oldEntry.uid; newEntry.tag = oldEntry.tag; newEntry.metered = oldEntry.metered; (entry) -> { return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(), NetworkStats.SET_ALL, entry.getTag(), entry.getMetered(), NetworkStats.ROAMING_ALL, NetworkStats.DEFAULT_NETWORK_ALL, entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets(), 0); }); } Loading @@ -1426,46 +1424,31 @@ public class StatsPullAtomService extends SystemService { * * This function iterates through each NetworkStats.Entry, sets its dimensions equal to the * default state (with the presumption that we don't want to slice on anything), and then * applies the slicer lambda to allow users to control which dimensions to slice on. This is * adapted from groupedByUid within NetworkStats.java * applies the slicer lambda to allow users to control which dimensions to slice on. * * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old * NetworkStats.Entry, that should be used to copy state from the old to the new. * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to * get the state from entry to replace the default value. * This is useful for slicing by particular dimensions. For example, if we wished * to slice by uid and tag, we could write the following lambda: * (new, old) -> { * new.uid = old.uid; * new.tag = old.tag; * (entry) -> { * return new NetworkStats.Entry(null, entry.getUid(), * NetworkStats.SET_ALL, entry.getTag(), * NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL, * NetworkStats.DEFAULT_NETWORK_ALL, * entry.getRxBytes(), entry.getRxPackets(), * entry.getTxBytes(), entry.getTxPackets(), 0); * } * If no slicer is provided, the data is not sliced by any dimensions. * @return new NeworkStats object appropriately sliced */ @NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats, @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) { final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); final NetworkStats.Entry entry = new NetworkStats.Entry(); entry.uid = NetworkStats.UID_ALL; entry.iface = NetworkStats.IFACE_ALL; entry.set = NetworkStats.SET_ALL; entry.tag = NetworkStats.TAG_NONE; entry.metered = NetworkStats.METERED_ALL; entry.roaming = NetworkStats.ROAMING_ALL; entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL; final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values for (int i = 0; i < stats.size(); i++) { stats.getValues(i, recycle); @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) { NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1); NetworkStats.Entry entry = new NetworkStats.Entry(); for (NetworkStats.Entry e : stats) { if (slicer != null) { slicer.accept(entry, recycle); entry = slicer.apply(e); } entry.rxBytes = recycle.rxBytes; entry.rxPackets = recycle.rxPackets; entry.txBytes = recycle.txBytes; entry.txPackets = recycle.txPackets; // Operations purposefully omitted since we don't use them for statsd. ret.combineValues(entry); ret = ret.addEntry(entry); } return ret; } Loading