Loading services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +127 −31 Original line number Original line Diff line number Diff line Loading @@ -21,11 +21,14 @@ import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Process.getUidForPid; import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; import static android.util.MathUtils.abs; import static android.util.MathUtils.abs; import static android.util.MathUtils.constrain; import static android.util.MathUtils.constrain; Loading @@ -38,6 +41,7 @@ import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines; import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -133,6 +137,7 @@ import com.android.internal.os.LooperStats; import com.android.internal.os.PowerProfile; import com.android.internal.os.PowerProfile; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FrameworkStatsLog; import com.android.server.BatteryService; import com.android.server.BatteryService; import com.android.server.BinderCallsStatsService; import com.android.server.BinderCallsStatsService; Loading Loading @@ -202,6 +207,12 @@ public class StatsPullAtomService extends SystemService { private static final long MILLIS_PER_SEC = 1000; private static final long MILLIS_PER_SEC = 1000; private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L; private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L; /** * The default bucket duration used when query a snapshot from NetworkStatsService. * The value should be sync with NetworkStatsService#DefaultNetworkStatsSettings#getUidConfig. */ private static final long NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS = HOURS.toMillis(2); private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000; private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000; private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXY; private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXY; Loading Loading @@ -279,6 +290,13 @@ public class StatsPullAtomService extends SystemService { private int mAppOpsSamplingRate = 0; private int mAppOpsSamplingRate = 0; // Baselines that stores list of NetworkStats right after initializing, with associated // information. This is used to calculate difference when pulling // {Mobile|Wifi}BytesTransfer* atoms. Note that this is not thread-safe, and must // only be accessed on the background thread. @NonNull private final List<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>(); public StatsPullAtomService(Context context) { public StatsPullAtomService(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -302,13 +320,17 @@ public class StatsPullAtomService extends SystemService { try { try { switch (atomTag) { switch (atomTag) { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: case FrameworkStatsLog.WIFI_BYTES_TRANSFER: return pullWifiBytesTransfer(atomTag, data, false); return pullDataBytesTransfer(atomTag, data, TRANSPORT_WIFI, /*withFgbg=*/ false); case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: return pullWifiBytesTransfer(atomTag, data, true); return pullDataBytesTransfer(atomTag, data, TRANSPORT_WIFI, /*withFgbg=*/ true); case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: return pullMobileBytesTransfer(atomTag, data, false); return pullDataBytesTransfer(atomTag, data, TRANSPORT_CELLULAR, /*withFgbg=*/ false); case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: return pullMobileBytesTransfer(atomTag, data, true); return pullDataBytesTransfer(atomTag, data, TRANSPORT_CELLULAR, /*withFgbg=*/ true); case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: return pullBluetoothBytesTransfer(atomTag, data); return pullBluetoothBytesTransfer(atomTag, data); case FrameworkStatsLog.KERNEL_WAKELOCK: case FrameworkStatsLog.KERNEL_WAKELOCK: Loading Loading @@ -444,9 +466,12 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getHandler().post(() -> { BackgroundThread.getHandler().post(() -> { nativeInit(); nativeInit(); initializePullersState(); initializePullersState(); registerAllPullers(); registerPullers(); registerEventListeners(); registerEventListeners(); }); }); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { // Network stats related pullers can only be initialized after service is ready. BackgroundThread.getHandler().post(() -> initAndRegisterNetworkStatsPullers()); } } } } Loading Loading @@ -521,15 +546,11 @@ public class StatsPullAtomService extends SystemService { } } } } void registerAllPullers() { void registerPullers() { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Registering all pullers with statsd"); Slog.d(TAG, "Registering pullers with statsd"); } } mStatsCallbackImpl = new StatsPullAtomCallbackImpl(); mStatsCallbackImpl = new StatsPullAtomCallbackImpl(); registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); registerBluetoothBytesTransfer(); registerBluetoothBytesTransfer(); registerKernelWakelock(); registerKernelWakelock(); registerCpuTimePerFreq(); registerCpuTimePerFreq(); Loading Loading @@ -590,6 +611,22 @@ public class StatsPullAtomService extends SystemService { registerSettingsStats(); registerSettingsStats(); } } private void initAndRegisterNetworkStatsPullers() { if (DEBUG) { Slog.d(TAG, "Registering NetworkStats pullers with statsd"); } // Initialize NetworkStats baselines. mNetworkStatsBaselines.addAll(collectWifiBytesTransferSnapshot(/*withFgbg=*/ false)); mNetworkStatsBaselines.addAll(collectWifiBytesTransferSnapshot(/*withFgbg=*/ true)); mNetworkStatsBaselines.addAll(collectMobileBytesTransferSnapshot(/*withFgbg=*/ false)); mNetworkStatsBaselines.addAll(collectMobileBytesTransferSnapshot(/*withFgbg=*/ true)); registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); } /** /** * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or Loading Loading @@ -723,37 +760,87 @@ public class StatsPullAtomService extends SystemService { ); ); } } private int pullWifiBytesTransfer( /** int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) { * A data class to store a NetworkStats object with information associated to it. final NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard(); */ final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg); private static class NetworkStatsExt { @NonNull public final NetworkStats stats; public final int transport; public final boolean withFgbg; // Return with PULL_SKIP to indicate there is an error. NetworkStatsExt(@NonNull NetworkStats stats, int transport, boolean withFgbg) { if (stats == null) return StatsManager.PULL_SKIP; this.stats = stats; this.transport = transport; this.withFgbg = withFgbg; } } addNetworkStats(atomTag, pulledData, stats, withFgbg, 0 /* ratType */); @NonNull return StatsManager.PULL_SUCCESS; private List<NetworkStatsExt> collectWifiBytesTransferSnapshot(boolean withFgbg) { final List<NetworkStatsExt> ret = new ArrayList<>(); final NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard(); final NetworkStats stats = getUidNetworkStatsSnapshot(template, withFgbg); if (stats != null) { ret.add(new NetworkStatsExt(stats, TRANSPORT_WIFI, withFgbg)); } return ret; } } private int pullMobileBytesTransfer( // Get a snapshot of mobile data usage. The snapshot contains NetworkStats with its associated int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) { // information, and wrapped by a list since multiple NetworkStatsExt objects might be collected. // TODO: Slice NetworkStats to multiple objects by RAT type or subscription. @NonNull private List<NetworkStatsExt> collectMobileBytesTransferSnapshot(boolean withFgbg) { final List<NetworkStatsExt> ret = new ArrayList<>(); final NetworkTemplate template = final NetworkTemplate template = NetworkTemplate.buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); NetworkTemplate.buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg); final NetworkStats stats = getUidNetworkStatsSnapshot(template, withFgbg); if (stats != null) { ret.add(new NetworkStatsExt(stats, TRANSPORT_CELLULAR, withFgbg)); } return ret; } private int pullDataBytesTransfer( int atomTag, @NonNull List<StatsEvent> pulledData, int transport, boolean withFgbg) { final List<NetworkStatsExt> current = (transport == TRANSPORT_CELLULAR ? collectMobileBytesTransferSnapshot(withFgbg) : collectWifiBytesTransferSnapshot(withFgbg)); if (current == null) { Slog.e(TAG, "current snapshot is null for " + atomTag + ", return."); return StatsManager.PULL_SKIP; } for (final NetworkStatsExt item : current) { final NetworkStatsExt baseline = CollectionUtils.find(mNetworkStatsBaselines, it -> it.withFgbg == item.withFgbg && it.transport == item.transport); // No matched baseline indicates error has occurred during initialization stage, // skip reporting anything since the snapshot is invalid. if (baseline == null) { Slog.e(TAG, "baseline is null for " + atomTag + ", transport=" + item.transport + " , withFgbg=" + withFgbg + ", return."); return StatsManager.PULL_SKIP; } final NetworkStatsExt diff = new NetworkStatsExt(item.stats.subtract( baseline.stats).removeEmptyEntries(), item.transport, item.withFgbg); // Return with PULL_SKIP to indicate there is an error. // If no diff, skip. if (stats == null) return StatsManager.PULL_SKIP; if (diff.stats.size() == 0) continue; addNetworkStats(atomTag, pulledData, stats, withFgbg, NETWORK_TYPE_ALL); addNetworkStats(atomTag, pulledData, diff); } return StatsManager.PULL_SUCCESS; return StatsManager.PULL_SUCCESS; } } private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStats stats, boolean withFgbg, int ratType) { @NonNull NetworkStatsExt statsExt) { int size = stats.size(); int size = statsExt.stats.size(); final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling for (int j = 0; j < size; j++) { for (int j = 0; j < size; j++) { stats.getValues(j, entry); statsExt.stats.getValues(j, entry); StatsEvent.Builder e = StatsEvent.newBuilder(); StatsEvent.Builder e = StatsEvent.newBuilder(); e.setAtomId(atomTag); e.setAtomId(atomTag); switch (atomTag) { switch (atomTag) { Loading @@ -765,7 +852,7 @@ public class StatsPullAtomService extends SystemService { } } e.writeInt(entry.uid); e.writeInt(entry.uid); e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); if (withFgbg) { if (statsExt.withFgbg) { e.writeInt(entry.set); e.writeInt(entry.set); } } e.writeLong(entry.rxBytes); e.writeLong(entry.rxBytes); Loading @@ -776,14 +863,23 @@ public class StatsPullAtomService extends SystemService { } } } } @Nullable private NetworkStats getUidNetworkStatsSinceBoot( /** * Create a snapshot of NetworkStats since boot, but add 1 bucket duration before boot as a * buffer to ensure at least one full bucket will be included. * Note that this should be only used to calculate diff since the snapshot might contains * some traffic before boot. */ @Nullable private NetworkStats getUidNetworkStatsSnapshot( @NonNull NetworkTemplate template, boolean withFgbg) { @NonNull NetworkTemplate template, boolean withFgbg) { final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); 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 { try { final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template, final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template, currentTimeInMillis - elapsedMillisSinceBoot, currentTimeInMillis, false); currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis, /*includeTags=*/false); return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid(); return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid(); } catch (RemoteException | NullPointerException e) { } catch (RemoteException | NullPointerException e) { Slog.e(TAG, "Pulling netstats for " + template Slog.e(TAG, "Pulling netstats for " + template Loading Loading
services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +127 −31 Original line number Original line Diff line number Diff line Loading @@ -21,11 +21,14 @@ import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Process.getUidForPid; import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; import static android.util.MathUtils.abs; import static android.util.MathUtils.abs; import static android.util.MathUtils.constrain; import static android.util.MathUtils.constrain; Loading @@ -38,6 +41,7 @@ import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines; import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MICROSECONDS; import android.annotation.NonNull; import android.annotation.NonNull; Loading Loading @@ -133,6 +137,7 @@ import com.android.internal.os.LooperStats; import com.android.internal.os.PowerProfile; import com.android.internal.os.PowerProfile; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.os.StoragedUidIoStatsReader; import com.android.internal.util.CollectionUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FrameworkStatsLog; import com.android.server.BatteryService; import com.android.server.BatteryService; import com.android.server.BinderCallsStatsService; import com.android.server.BinderCallsStatsService; Loading Loading @@ -202,6 +207,12 @@ public class StatsPullAtomService extends SystemService { private static final long MILLIS_PER_SEC = 1000; private static final long MILLIS_PER_SEC = 1000; private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L; private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L; /** * The default bucket duration used when query a snapshot from NetworkStatsService. * The value should be sync with NetworkStatsService#DefaultNetworkStatsSettings#getUidConfig. */ private static final long NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS = HOURS.toMillis(2); private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000; private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000; private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8; private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXY; private static final int OP_FLAGS_PULLED = OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXY; Loading Loading @@ -279,6 +290,13 @@ public class StatsPullAtomService extends SystemService { private int mAppOpsSamplingRate = 0; private int mAppOpsSamplingRate = 0; // Baselines that stores list of NetworkStats right after initializing, with associated // information. This is used to calculate difference when pulling // {Mobile|Wifi}BytesTransfer* atoms. Note that this is not thread-safe, and must // only be accessed on the background thread. @NonNull private final List<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>(); public StatsPullAtomService(Context context) { public StatsPullAtomService(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -302,13 +320,17 @@ public class StatsPullAtomService extends SystemService { try { try { switch (atomTag) { switch (atomTag) { case FrameworkStatsLog.WIFI_BYTES_TRANSFER: case FrameworkStatsLog.WIFI_BYTES_TRANSFER: return pullWifiBytesTransfer(atomTag, data, false); return pullDataBytesTransfer(atomTag, data, TRANSPORT_WIFI, /*withFgbg=*/ false); case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: return pullWifiBytesTransfer(atomTag, data, true); return pullDataBytesTransfer(atomTag, data, TRANSPORT_WIFI, /*withFgbg=*/ true); case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: return pullMobileBytesTransfer(atomTag, data, false); return pullDataBytesTransfer(atomTag, data, TRANSPORT_CELLULAR, /*withFgbg=*/ false); case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG: return pullMobileBytesTransfer(atomTag, data, true); return pullDataBytesTransfer(atomTag, data, TRANSPORT_CELLULAR, /*withFgbg=*/ true); case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER: return pullBluetoothBytesTransfer(atomTag, data); return pullBluetoothBytesTransfer(atomTag, data); case FrameworkStatsLog.KERNEL_WAKELOCK: case FrameworkStatsLog.KERNEL_WAKELOCK: Loading Loading @@ -444,9 +466,12 @@ public class StatsPullAtomService extends SystemService { BackgroundThread.getHandler().post(() -> { BackgroundThread.getHandler().post(() -> { nativeInit(); nativeInit(); initializePullersState(); initializePullersState(); registerAllPullers(); registerPullers(); registerEventListeners(); registerEventListeners(); }); }); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { // Network stats related pullers can only be initialized after service is ready. BackgroundThread.getHandler().post(() -> initAndRegisterNetworkStatsPullers()); } } } } Loading Loading @@ -521,15 +546,11 @@ public class StatsPullAtomService extends SystemService { } } } } void registerAllPullers() { void registerPullers() { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Registering all pullers with statsd"); Slog.d(TAG, "Registering pullers with statsd"); } } mStatsCallbackImpl = new StatsPullAtomCallbackImpl(); mStatsCallbackImpl = new StatsPullAtomCallbackImpl(); registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); registerBluetoothBytesTransfer(); registerBluetoothBytesTransfer(); registerKernelWakelock(); registerKernelWakelock(); registerCpuTimePerFreq(); registerCpuTimePerFreq(); Loading Loading @@ -590,6 +611,22 @@ public class StatsPullAtomService extends SystemService { registerSettingsStats(); registerSettingsStats(); } } private void initAndRegisterNetworkStatsPullers() { if (DEBUG) { Slog.d(TAG, "Registering NetworkStats pullers with statsd"); } // Initialize NetworkStats baselines. mNetworkStatsBaselines.addAll(collectWifiBytesTransferSnapshot(/*withFgbg=*/ false)); mNetworkStatsBaselines.addAll(collectWifiBytesTransferSnapshot(/*withFgbg=*/ true)); mNetworkStatsBaselines.addAll(collectMobileBytesTransferSnapshot(/*withFgbg=*/ false)); mNetworkStatsBaselines.addAll(collectMobileBytesTransferSnapshot(/*withFgbg=*/ true)); registerWifiBytesTransfer(); registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); } /** /** * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * Return the {@code INetworkStatsSession} object that holds the necessary properties needed * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or Loading Loading @@ -723,37 +760,87 @@ public class StatsPullAtomService extends SystemService { ); ); } } private int pullWifiBytesTransfer( /** int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) { * A data class to store a NetworkStats object with information associated to it. final NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard(); */ final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg); private static class NetworkStatsExt { @NonNull public final NetworkStats stats; public final int transport; public final boolean withFgbg; // Return with PULL_SKIP to indicate there is an error. NetworkStatsExt(@NonNull NetworkStats stats, int transport, boolean withFgbg) { if (stats == null) return StatsManager.PULL_SKIP; this.stats = stats; this.transport = transport; this.withFgbg = withFgbg; } } addNetworkStats(atomTag, pulledData, stats, withFgbg, 0 /* ratType */); @NonNull return StatsManager.PULL_SUCCESS; private List<NetworkStatsExt> collectWifiBytesTransferSnapshot(boolean withFgbg) { final List<NetworkStatsExt> ret = new ArrayList<>(); final NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard(); final NetworkStats stats = getUidNetworkStatsSnapshot(template, withFgbg); if (stats != null) { ret.add(new NetworkStatsExt(stats, TRANSPORT_WIFI, withFgbg)); } return ret; } } private int pullMobileBytesTransfer( // Get a snapshot of mobile data usage. The snapshot contains NetworkStats with its associated int atomTag, @NonNull List<StatsEvent> pulledData, boolean withFgbg) { // information, and wrapped by a list since multiple NetworkStatsExt objects might be collected. // TODO: Slice NetworkStats to multiple objects by RAT type or subscription. @NonNull private List<NetworkStatsExt> collectMobileBytesTransferSnapshot(boolean withFgbg) { final List<NetworkStatsExt> ret = new ArrayList<>(); final NetworkTemplate template = final NetworkTemplate template = NetworkTemplate.buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); NetworkTemplate.buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL); final NetworkStats stats = getUidNetworkStatsSinceBoot(template, withFgbg); final NetworkStats stats = getUidNetworkStatsSnapshot(template, withFgbg); if (stats != null) { ret.add(new NetworkStatsExt(stats, TRANSPORT_CELLULAR, withFgbg)); } return ret; } private int pullDataBytesTransfer( int atomTag, @NonNull List<StatsEvent> pulledData, int transport, boolean withFgbg) { final List<NetworkStatsExt> current = (transport == TRANSPORT_CELLULAR ? collectMobileBytesTransferSnapshot(withFgbg) : collectWifiBytesTransferSnapshot(withFgbg)); if (current == null) { Slog.e(TAG, "current snapshot is null for " + atomTag + ", return."); return StatsManager.PULL_SKIP; } for (final NetworkStatsExt item : current) { final NetworkStatsExt baseline = CollectionUtils.find(mNetworkStatsBaselines, it -> it.withFgbg == item.withFgbg && it.transport == item.transport); // No matched baseline indicates error has occurred during initialization stage, // skip reporting anything since the snapshot is invalid. if (baseline == null) { Slog.e(TAG, "baseline is null for " + atomTag + ", transport=" + item.transport + " , withFgbg=" + withFgbg + ", return."); return StatsManager.PULL_SKIP; } final NetworkStatsExt diff = new NetworkStatsExt(item.stats.subtract( baseline.stats).removeEmptyEntries(), item.transport, item.withFgbg); // Return with PULL_SKIP to indicate there is an error. // If no diff, skip. if (stats == null) return StatsManager.PULL_SKIP; if (diff.stats.size() == 0) continue; addNetworkStats(atomTag, pulledData, stats, withFgbg, NETWORK_TYPE_ALL); addNetworkStats(atomTag, pulledData, diff); } return StatsManager.PULL_SUCCESS; return StatsManager.PULL_SUCCESS; } } private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret, @NonNull NetworkStats stats, boolean withFgbg, int ratType) { @NonNull NetworkStatsExt statsExt) { int size = stats.size(); int size = statsExt.stats.size(); final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling for (int j = 0; j < size; j++) { for (int j = 0; j < size; j++) { stats.getValues(j, entry); statsExt.stats.getValues(j, entry); StatsEvent.Builder e = StatsEvent.newBuilder(); StatsEvent.Builder e = StatsEvent.newBuilder(); e.setAtomId(atomTag); e.setAtomId(atomTag); switch (atomTag) { switch (atomTag) { Loading @@ -765,7 +852,7 @@ public class StatsPullAtomService extends SystemService { } } e.writeInt(entry.uid); e.writeInt(entry.uid); e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); e.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true); if (withFgbg) { if (statsExt.withFgbg) { e.writeInt(entry.set); e.writeInt(entry.set); } } e.writeLong(entry.rxBytes); e.writeLong(entry.rxBytes); Loading @@ -776,14 +863,23 @@ public class StatsPullAtomService extends SystemService { } } } } @Nullable private NetworkStats getUidNetworkStatsSinceBoot( /** * Create a snapshot of NetworkStats since boot, but add 1 bucket duration before boot as a * buffer to ensure at least one full bucket will be included. * Note that this should be only used to calculate diff since the snapshot might contains * some traffic before boot. */ @Nullable private NetworkStats getUidNetworkStatsSnapshot( @NonNull NetworkTemplate template, boolean withFgbg) { @NonNull NetworkTemplate template, boolean withFgbg) { final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long elapsedMillisSinceBoot = SystemClock.elapsedRealtime(); final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro()); 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 { try { final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template, final NetworkStats stats = getNetworkStatsSession().getSummaryForAllUid(template, currentTimeInMillis - elapsedMillisSinceBoot, currentTimeInMillis, false); currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration, currentTimeInMillis, /*includeTags=*/false); return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid(); return withFgbg ? rollupNetworkStatsByFgbg(stats) : stats.groupedByUid(); } catch (RemoteException | NullPointerException e) { } catch (RemoteException | NullPointerException e) { Slog.e(TAG, "Pulling netstats for " + template Slog.e(TAG, "Pulling netstats for " + template Loading