Loading services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ java_library_static { "backup_flags_lib", "policy_flags_lib", "net_flags_lib", "stats_flags_lib", ], javac_shard_size: 50, javacflags: [ Loading services/core/java/com/android/server/am/ActivityManagerService.java +19 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,8 @@ import com.android.server.pm.pkg.SELinuxUtil; import com.android.server.pm.snapshot.PackageDataSnapshot; import com.android.server.power.stats.BatteryStatsImpl; import com.android.server.sdksandbox.SdkSandboxManagerLocal; import com.android.server.stats.pull.StatsPullAtomService; import com.android.server.stats.pull.StatsPullAtomServiceInternal; import com.android.server.uri.GrantUri; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriGrantsManagerInternal; Loading Loading @@ -1308,6 +1310,8 @@ public class ActivityManagerService extends IActivityManager.Stub */ final BatteryStatsService mBatteryStatsService; StatsPullAtomServiceInternal mStatsPullAtomServiceInternal; /** * Information about component usage */ Loading Loading @@ -16554,6 +16558,21 @@ public class ActivityManagerService extends IActivityManager.Stub final @ProcessCapability int capability) { mBatteryStatsService.noteUidProcessState(uid, state); mAppOpsService.updateUidProcState(uid, state, capability); if (StatsPullAtomService.ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { try { if (mStatsPullAtomServiceInternal == null) { mStatsPullAtomServiceInternal = LocalServices.getService( StatsPullAtomServiceInternal.class); } if (mStatsPullAtomServiceInternal != null) { mStatsPullAtomServiceInternal.noteUidProcessState(uid, state); } else { Slog.d(TAG, "StatsPullAtomService not ready yet"); } } catch (Exception e) { Slog.e(TAG, "Exception during logging uid proc state change event", e); } } if (mTrackingAssociations) { for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) { ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents services/core/java/com/android/server/stats/Android.bp 0 → 100644 +12 −0 Original line number Diff line number Diff line aconfig_declarations { name: "stats_flags", package: "com.android.server.stats", srcs: [ "stats_flags.aconfig", ], } java_aconfig_library { name: "stats_flags_lib", aconfig_declarations: "stats_flags", } services/core/java/com/android/server/stats/pull/AggregatedMobileDataStatsPuller.java 0 → 100644 +285 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.stats.pull; import android.app.ActivityManager; import android.app.StatsManager; import android.app.usage.NetworkStatsManager; import android.net.NetworkStats; import android.os.Handler; import android.os.HandlerThread; import android.os.Trace; import android.util.ArrayMap; import android.util.Slog; import android.util.SparseIntArray; import android.util.StatsEvent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; import java.util.List; import java.util.Map; /** * Aggregates Mobile Data Usage by process state per uid */ class AggregatedMobileDataStatsPuller { private static final String TAG = "AggregatedMobileDataStatsPuller"; private static final boolean DEBUG = false; private static class UidProcState { private final int mUid; private final int mState; UidProcState(int uid, int state) { mUid = uid; mState = state; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof UidProcState key)) return false; return mUid == key.mUid && mState == key.mState; } @Override public int hashCode() { int result = mUid; result = 31 * result + mState; return result; } public int getUid() { return mUid; } public int getState() { return mState; } } private static class MobileDataStats { private long mRxPackets = 0; private long mTxPackets = 0; private long mRxBytes = 0; private long mTxBytes = 0; public long getRxPackets() { return mRxPackets; } public long getTxPackets() { return mTxPackets; } public long getRxBytes() { return mRxBytes; } public long getTxBytes() { return mTxBytes; } public void addRxPackets(long rxPackets) { mRxPackets += rxPackets; } public void addTxPackets(long txPackets) { mTxPackets += txPackets; } public void addRxBytes(long rxBytes) { mRxBytes += rxBytes; } public void addTxBytes(long txBytes) { mTxBytes += txBytes; } public boolean isEmpty() { return mRxPackets == 0 && mTxPackets == 0 && mRxBytes == 0 && mTxBytes == 0; } } private final Object mLock = new Object(); @GuardedBy("mLock") private final Map<UidProcState, MobileDataStats> mUidStats; private final SparseIntArray mUidPreviousState; private NetworkStats mLastMobileUidStats = new NetworkStats(0, -1); private final NetworkStatsManager mNetworkStatsManager; private final Handler mMobileDataStatsHandler; AggregatedMobileDataStatsPuller(NetworkStatsManager networkStatsManager) { mUidStats = new ArrayMap<>(); mUidPreviousState = new SparseIntArray(); mNetworkStatsManager = networkStatsManager; if (mNetworkStatsManager != null) { updateNetworkStats(mNetworkStatsManager); } HandlerThread mMobileDataStatsHandlerThread = new HandlerThread("MobileDataStatsHandler"); mMobileDataStatsHandlerThread.start(); mMobileDataStatsHandler = new Handler(mMobileDataStatsHandlerThread.getLooper()); } public void noteUidProcessState(int uid, int state, long unusedElapsedRealtime, long unusedUptime) { mMobileDataStatsHandler.post( () -> { noteUidProcessStateImpl(uid, state); }); } public int pullDataBytesTransfer(List<StatsEvent> data) { synchronized (mLock) { return pullDataBytesTransferLocked(data); } } @GuardedBy("mLock") private MobileDataStats getUidStatsForPreviousStateLocked(int uid) { final int previousState = mUidPreviousState.get(uid, ActivityManager.PROCESS_STATE_UNKNOWN); if (DEBUG && previousState == ActivityManager.PROCESS_STATE_UNKNOWN) { Slog.d(TAG, "getUidStatsForPreviousStateLocked() no prev state info for uid " + uid + ". Tracking stats with ActivityManager.PROCESS_STATE_UNKNOWN"); } final UidProcState statsKey = new UidProcState(uid, previousState); MobileDataStats stats; if (mUidStats.containsKey(statsKey)) { stats = mUidStats.get(statsKey); } else { stats = new MobileDataStats(); mUidStats.put(statsKey, stats); } return stats; } private void noteUidProcessStateImpl(int uid, int state) { // noteUidProcessStateLocked can be called back to back several times while // the updateNetworkStatsLocked loops over several stats for multiple uids // and during the first call in a batch of proc state change event it can // contain info for uid with unknown previous state yet which can happen due to a few // reasons: // - app was just started // - app was started before the ActivityManagerService // as result stats would be created with state == ActivityManager.PROCESS_STATE_UNKNOWN if (mNetworkStatsManager != null) { updateNetworkStats(mNetworkStatsManager); } else { Slog.w(TAG, "noteUidProcessStateLocked() can not get mNetworkStatsManager"); } mUidPreviousState.put(uid, state); } private void updateNetworkStats(NetworkStatsManager networkStatsManager) { if (DEBUG) { if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, TAG + "-updateNetworkStats"); } } final NetworkStats latestStats = networkStatsManager.getMobileUidStats(); if (isEmpty(latestStats)) { if (DEBUG) { Slog.w(TAG, "getMobileUidStats() failed"); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } return; } NetworkStats delta = latestStats.subtract(mLastMobileUidStats); mLastMobileUidStats = latestStats; if (!isEmpty(delta)) { updateNetworkStatsDelta(delta); } else if (DEBUG) { Slog.w(TAG, "updateNetworkStats() no delta"); } if (DEBUG) { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } } private void updateNetworkStatsDelta(NetworkStats delta) { synchronized (mLock) { for (NetworkStats.Entry entry : delta) { if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) { continue; } MobileDataStats stats = getUidStatsForPreviousStateLocked(entry.getUid()); stats.addTxBytes(entry.getTxBytes()); stats.addRxBytes(entry.getRxBytes()); stats.addTxPackets(entry.getTxPackets()); stats.addRxPackets(entry.getRxPackets()); } } } @GuardedBy("mLock") private int pullDataBytesTransferLocked(List<StatsEvent> pulledData) { if (DEBUG) { Slog.d(TAG, "pullDataBytesTransferLocked() start"); } for (Map.Entry<UidProcState, MobileDataStats> uidStats : mUidStats.entrySet()) { if (!uidStats.getValue().isEmpty()) { MobileDataStats stats = uidStats.getValue(); pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE, uidStats.getKey().getUid(), ActivityManager.processStateAmToProto(uidStats.getKey().getState()), stats.getRxBytes(), stats.getRxPackets(), stats.getTxBytes(), stats.getTxPackets())); } } if (DEBUG) { Slog.d(TAG, "pullDataBytesTransferLocked() done. results count " + pulledData.size()); } if (!pulledData.isEmpty()) { return StatsManager.PULL_SUCCESS; } return StatsManager.PULL_SKIP; } private static boolean isEmpty(NetworkStats stats) { long totalRxPackets = 0; long totalTxPackets = 0; for (NetworkStats.Entry entry : stats) { if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) { continue; } totalRxPackets += entry.getRxPackets(); totalTxPackets += entry.getTxPackets(); // at least one non empty entry located break; } final long totalPackets = totalRxPackets + totalTxPackets; return totalPackets == 0; } } services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +58 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STA import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY; import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePuller; import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs; import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines; Loading Loading @@ -409,6 +410,15 @@ public class StatsPullAtomService extends SystemService { @GuardedBy("mKeystoreLock") private IKeystoreMetrics mIKeystoreMetrics; private AggregatedMobileDataStatsPuller mAggregatedMobileDataStatsPuller = null; /** * Whether or not to enable the new puller with aggregation by process state per uid on a * system server side. */ public static final boolean ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER = addMobileBytesTransferByProcStatePuller(); // Puller locks private final Object mDataBytesTransferLock = new Object(); private final Object mBluetoothBytesTransferLock = new Object(); Loading Loading @@ -469,6 +479,20 @@ public class StatsPullAtomService extends SystemService { mContext = context; } private final class StatsPullAtomServiceInternalImpl extends StatsPullAtomServiceInternal { @Override public void noteUidProcessState(int uid, int state) { if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER && mAggregatedMobileDataStatsPuller != null) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); mAggregatedMobileDataStatsPuller.noteUidProcessState(uid, state, elapsedRealtime, uptime); } } } private native void initializeNativePullers(); /** Loading @@ -486,6 +510,11 @@ public class StatsPullAtomService extends SystemService { } try { switch (atomTag) { case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE: if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER && mAggregatedMobileDataStatsPuller != null) { return mAggregatedMobileDataStatsPuller.pullDataBytesTransfer(data); } case FrameworkStatsLog.WIFI_BYTES_TRANSFER: case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: Loading Loading @@ -776,7 +805,10 @@ public class StatsPullAtomService extends SystemService { @Override public void onStart() { // no op if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { LocalServices.addService(StatsPullAtomServiceInternal.class, new StatsPullAtomServiceInternalImpl()); } } @Override Loading Loading @@ -811,6 +843,9 @@ public class StatsPullAtomService extends SystemService { mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class); initMobileDataStatsPuller(); // Initialize DiskIO mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(); Loading Loading @@ -972,6 +1007,18 @@ public class StatsPullAtomService extends SystemService { registerCachedAppsHighWatermarkPuller(); } private void initMobileDataStatsPuller() { if (DEBUG) { Slog.d(TAG, "ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER = " + ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER); } if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { mAggregatedMobileDataStatsPuller = new AggregatedMobileDataStatsPuller(mNetworkStatsManager); } } private void initAndRegisterNetworkStatsPullers() { if (DEBUG) { Slog.d(TAG, "Registering NetworkStats pullers with statsd"); Loading Loading @@ -1013,6 +1060,9 @@ public class StatsPullAtomService extends SystemService { registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { registerMobileBytesTransferByProcState(); } registerBytesTransferByTagAndMetered(); registerDataUsageBytesTransfer(); registerOemManagedBytesTransfer(); Loading @@ -1021,6 +1071,13 @@ public class StatsPullAtomService extends SystemService { } } private void registerMobileBytesTransferByProcState() { final int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE; PullAtomMetadata metadata = new PullAtomMetadata.Builder().setAdditiveFields(new int[] {3, 4, 5, 6}).build(); mStatsManager.setPullAtomCallback(tagId, metadata, DIRECT_EXECUTOR, mStatsCallbackImpl); } private void initAndRegisterDeferredPullers() { mUwbManager = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB) ? mContext.getSystemService(UwbManager.class) : null; Loading Loading
services/core/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -214,6 +214,7 @@ java_library_static { "backup_flags_lib", "policy_flags_lib", "net_flags_lib", "stats_flags_lib", ], javac_shard_size: 50, javacflags: [ Loading
services/core/java/com/android/server/am/ActivityManagerService.java +19 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,8 @@ import com.android.server.pm.pkg.SELinuxUtil; import com.android.server.pm.snapshot.PackageDataSnapshot; import com.android.server.power.stats.BatteryStatsImpl; import com.android.server.sdksandbox.SdkSandboxManagerLocal; import com.android.server.stats.pull.StatsPullAtomService; import com.android.server.stats.pull.StatsPullAtomServiceInternal; import com.android.server.uri.GrantUri; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriGrantsManagerInternal; Loading Loading @@ -1308,6 +1310,8 @@ public class ActivityManagerService extends IActivityManager.Stub */ final BatteryStatsService mBatteryStatsService; StatsPullAtomServiceInternal mStatsPullAtomServiceInternal; /** * Information about component usage */ Loading Loading @@ -16554,6 +16558,21 @@ public class ActivityManagerService extends IActivityManager.Stub final @ProcessCapability int capability) { mBatteryStatsService.noteUidProcessState(uid, state); mAppOpsService.updateUidProcState(uid, state, capability); if (StatsPullAtomService.ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { try { if (mStatsPullAtomServiceInternal == null) { mStatsPullAtomServiceInternal = LocalServices.getService( StatsPullAtomServiceInternal.class); } if (mStatsPullAtomServiceInternal != null) { mStatsPullAtomServiceInternal.noteUidProcessState(uid, state); } else { Slog.d(TAG, "StatsPullAtomService not ready yet"); } } catch (Exception e) { Slog.e(TAG, "Exception during logging uid proc state change event", e); } } if (mTrackingAssociations) { for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) { ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents
services/core/java/com/android/server/stats/Android.bp 0 → 100644 +12 −0 Original line number Diff line number Diff line aconfig_declarations { name: "stats_flags", package: "com.android.server.stats", srcs: [ "stats_flags.aconfig", ], } java_aconfig_library { name: "stats_flags_lib", aconfig_declarations: "stats_flags", }
services/core/java/com/android/server/stats/pull/AggregatedMobileDataStatsPuller.java 0 → 100644 +285 −0 Original line number Diff line number Diff line /* * Copyright 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.stats.pull; import android.app.ActivityManager; import android.app.StatsManager; import android.app.usage.NetworkStatsManager; import android.net.NetworkStats; import android.os.Handler; import android.os.HandlerThread; import android.os.Trace; import android.util.ArrayMap; import android.util.Slog; import android.util.SparseIntArray; import android.util.StatsEvent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FrameworkStatsLog; import java.util.List; import java.util.Map; /** * Aggregates Mobile Data Usage by process state per uid */ class AggregatedMobileDataStatsPuller { private static final String TAG = "AggregatedMobileDataStatsPuller"; private static final boolean DEBUG = false; private static class UidProcState { private final int mUid; private final int mState; UidProcState(int uid, int state) { mUid = uid; mState = state; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof UidProcState key)) return false; return mUid == key.mUid && mState == key.mState; } @Override public int hashCode() { int result = mUid; result = 31 * result + mState; return result; } public int getUid() { return mUid; } public int getState() { return mState; } } private static class MobileDataStats { private long mRxPackets = 0; private long mTxPackets = 0; private long mRxBytes = 0; private long mTxBytes = 0; public long getRxPackets() { return mRxPackets; } public long getTxPackets() { return mTxPackets; } public long getRxBytes() { return mRxBytes; } public long getTxBytes() { return mTxBytes; } public void addRxPackets(long rxPackets) { mRxPackets += rxPackets; } public void addTxPackets(long txPackets) { mTxPackets += txPackets; } public void addRxBytes(long rxBytes) { mRxBytes += rxBytes; } public void addTxBytes(long txBytes) { mTxBytes += txBytes; } public boolean isEmpty() { return mRxPackets == 0 && mTxPackets == 0 && mRxBytes == 0 && mTxBytes == 0; } } private final Object mLock = new Object(); @GuardedBy("mLock") private final Map<UidProcState, MobileDataStats> mUidStats; private final SparseIntArray mUidPreviousState; private NetworkStats mLastMobileUidStats = new NetworkStats(0, -1); private final NetworkStatsManager mNetworkStatsManager; private final Handler mMobileDataStatsHandler; AggregatedMobileDataStatsPuller(NetworkStatsManager networkStatsManager) { mUidStats = new ArrayMap<>(); mUidPreviousState = new SparseIntArray(); mNetworkStatsManager = networkStatsManager; if (mNetworkStatsManager != null) { updateNetworkStats(mNetworkStatsManager); } HandlerThread mMobileDataStatsHandlerThread = new HandlerThread("MobileDataStatsHandler"); mMobileDataStatsHandlerThread.start(); mMobileDataStatsHandler = new Handler(mMobileDataStatsHandlerThread.getLooper()); } public void noteUidProcessState(int uid, int state, long unusedElapsedRealtime, long unusedUptime) { mMobileDataStatsHandler.post( () -> { noteUidProcessStateImpl(uid, state); }); } public int pullDataBytesTransfer(List<StatsEvent> data) { synchronized (mLock) { return pullDataBytesTransferLocked(data); } } @GuardedBy("mLock") private MobileDataStats getUidStatsForPreviousStateLocked(int uid) { final int previousState = mUidPreviousState.get(uid, ActivityManager.PROCESS_STATE_UNKNOWN); if (DEBUG && previousState == ActivityManager.PROCESS_STATE_UNKNOWN) { Slog.d(TAG, "getUidStatsForPreviousStateLocked() no prev state info for uid " + uid + ". Tracking stats with ActivityManager.PROCESS_STATE_UNKNOWN"); } final UidProcState statsKey = new UidProcState(uid, previousState); MobileDataStats stats; if (mUidStats.containsKey(statsKey)) { stats = mUidStats.get(statsKey); } else { stats = new MobileDataStats(); mUidStats.put(statsKey, stats); } return stats; } private void noteUidProcessStateImpl(int uid, int state) { // noteUidProcessStateLocked can be called back to back several times while // the updateNetworkStatsLocked loops over several stats for multiple uids // and during the first call in a batch of proc state change event it can // contain info for uid with unknown previous state yet which can happen due to a few // reasons: // - app was just started // - app was started before the ActivityManagerService // as result stats would be created with state == ActivityManager.PROCESS_STATE_UNKNOWN if (mNetworkStatsManager != null) { updateNetworkStats(mNetworkStatsManager); } else { Slog.w(TAG, "noteUidProcessStateLocked() can not get mNetworkStatsManager"); } mUidPreviousState.put(uid, state); } private void updateNetworkStats(NetworkStatsManager networkStatsManager) { if (DEBUG) { if (Trace.isTagEnabled(Trace.TRACE_TAG_SYSTEM_SERVER)) { Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, TAG + "-updateNetworkStats"); } } final NetworkStats latestStats = networkStatsManager.getMobileUidStats(); if (isEmpty(latestStats)) { if (DEBUG) { Slog.w(TAG, "getMobileUidStats() failed"); Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } return; } NetworkStats delta = latestStats.subtract(mLastMobileUidStats); mLastMobileUidStats = latestStats; if (!isEmpty(delta)) { updateNetworkStatsDelta(delta); } else if (DEBUG) { Slog.w(TAG, "updateNetworkStats() no delta"); } if (DEBUG) { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } } private void updateNetworkStatsDelta(NetworkStats delta) { synchronized (mLock) { for (NetworkStats.Entry entry : delta) { if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) { continue; } MobileDataStats stats = getUidStatsForPreviousStateLocked(entry.getUid()); stats.addTxBytes(entry.getTxBytes()); stats.addRxBytes(entry.getRxBytes()); stats.addTxPackets(entry.getTxPackets()); stats.addRxPackets(entry.getRxPackets()); } } } @GuardedBy("mLock") private int pullDataBytesTransferLocked(List<StatsEvent> pulledData) { if (DEBUG) { Slog.d(TAG, "pullDataBytesTransferLocked() start"); } for (Map.Entry<UidProcState, MobileDataStats> uidStats : mUidStats.entrySet()) { if (!uidStats.getValue().isEmpty()) { MobileDataStats stats = uidStats.getValue(); pulledData.add(FrameworkStatsLog.buildStatsEvent( FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE, uidStats.getKey().getUid(), ActivityManager.processStateAmToProto(uidStats.getKey().getState()), stats.getRxBytes(), stats.getRxPackets(), stats.getTxBytes(), stats.getTxPackets())); } } if (DEBUG) { Slog.d(TAG, "pullDataBytesTransferLocked() done. results count " + pulledData.size()); } if (!pulledData.isEmpty()) { return StatsManager.PULL_SUCCESS; } return StatsManager.PULL_SKIP; } private static boolean isEmpty(NetworkStats stats) { long totalRxPackets = 0; long totalTxPackets = 0; for (NetworkStats.Entry entry : stats) { if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) { continue; } totalRxPackets += entry.getRxPackets(); totalTxPackets += entry.getTxPackets(); // at least one non empty entry located break; } final long totalPackets = totalRxPackets + totalTxPackets; return totalPackets == 0; } }
services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +58 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STA import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY; import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN; import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePuller; import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs; import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs; import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines; Loading Loading @@ -409,6 +410,15 @@ public class StatsPullAtomService extends SystemService { @GuardedBy("mKeystoreLock") private IKeystoreMetrics mIKeystoreMetrics; private AggregatedMobileDataStatsPuller mAggregatedMobileDataStatsPuller = null; /** * Whether or not to enable the new puller with aggregation by process state per uid on a * system server side. */ public static final boolean ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER = addMobileBytesTransferByProcStatePuller(); // Puller locks private final Object mDataBytesTransferLock = new Object(); private final Object mBluetoothBytesTransferLock = new Object(); Loading Loading @@ -469,6 +479,20 @@ public class StatsPullAtomService extends SystemService { mContext = context; } private final class StatsPullAtomServiceInternalImpl extends StatsPullAtomServiceInternal { @Override public void noteUidProcessState(int uid, int state) { if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER && mAggregatedMobileDataStatsPuller != null) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); mAggregatedMobileDataStatsPuller.noteUidProcessState(uid, state, elapsedRealtime, uptime); } } } private native void initializeNativePullers(); /** Loading @@ -486,6 +510,11 @@ public class StatsPullAtomService extends SystemService { } try { switch (atomTag) { case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE: if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER && mAggregatedMobileDataStatsPuller != null) { return mAggregatedMobileDataStatsPuller.pullDataBytesTransfer(data); } case FrameworkStatsLog.WIFI_BYTES_TRANSFER: case FrameworkStatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG: case FrameworkStatsLog.MOBILE_BYTES_TRANSFER: Loading Loading @@ -776,7 +805,10 @@ public class StatsPullAtomService extends SystemService { @Override public void onStart() { // no op if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { LocalServices.addService(StatsPullAtomServiceInternal.class, new StatsPullAtomServiceInternalImpl()); } } @Override Loading Loading @@ -811,6 +843,9 @@ public class StatsPullAtomService extends SystemService { mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager); mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class); mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class); initMobileDataStatsPuller(); // Initialize DiskIO mStoragedUidIoStatsReader = new StoragedUidIoStatsReader(); Loading Loading @@ -972,6 +1007,18 @@ public class StatsPullAtomService extends SystemService { registerCachedAppsHighWatermarkPuller(); } private void initMobileDataStatsPuller() { if (DEBUG) { Slog.d(TAG, "ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER = " + ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER); } if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { mAggregatedMobileDataStatsPuller = new AggregatedMobileDataStatsPuller(mNetworkStatsManager); } } private void initAndRegisterNetworkStatsPullers() { if (DEBUG) { Slog.d(TAG, "Registering NetworkStats pullers with statsd"); Loading Loading @@ -1013,6 +1060,9 @@ public class StatsPullAtomService extends SystemService { registerWifiBytesTransferBackground(); registerMobileBytesTransfer(); registerMobileBytesTransferBackground(); if (ENABLE_MOBILE_DATA_STATS_AGGREGATED_PULLER) { registerMobileBytesTransferByProcState(); } registerBytesTransferByTagAndMetered(); registerDataUsageBytesTransfer(); registerOemManagedBytesTransfer(); Loading @@ -1021,6 +1071,13 @@ public class StatsPullAtomService extends SystemService { } } private void registerMobileBytesTransferByProcState() { final int tagId = FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_PROC_STATE; PullAtomMetadata metadata = new PullAtomMetadata.Builder().setAdditiveFields(new int[] {3, 4, 5, 6}).build(); mStatsManager.setPullAtomCallback(tagId, metadata, DIRECT_EXECUTOR, mStatsCallbackImpl); } private void initAndRegisterDeferredPullers() { mUwbManager = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB) ? mContext.getSystemService(UwbManager.class) : null; Loading