summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessState.java70
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessStats.java76
-rw-r--r--core/java/com/android/internal/app/procstats/StatsEventOutput.java98
-rw-r--r--core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java159
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java161
5 files changed, 528 insertions, 36 deletions
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 72b9cd272d02..818a50366115 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -73,6 +73,7 @@ import com.android.internal.app.procstats.ProcessStats.TotalMemoryUseCollection;
import java.io.PrintWriter;
import java.util.Comparator;
+import java.util.concurrent.TimeUnit;
public final class ProcessState {
private static final String TAG = "ProcessStats";
@@ -1542,6 +1543,75 @@ public final class ProcessState {
proto.write(fieldId, procName);
}
+ /** Dumps the duration of each state to statsEventOutput. */
+ public void dumpStateDurationToStatsd(
+ int atomTag, ProcessStats processStats, StatsEventOutput statsEventOutput) {
+ long topMs = 0;
+ long fgsMs = 0;
+ long boundTopMs = 0;
+ long boundFgsMs = 0;
+ long importantForegroundMs = 0;
+ long cachedMs = 0;
+ long frozenMs = 0;
+ long otherMs = 0;
+ for (int i = 0, size = mDurations.getKeyCount(); i < size; i++) {
+ final int key = mDurations.getKeyAt(i);
+ final int type = SparseMappingTable.getIdFromKey(key);
+ int procStateIndex = type % STATE_COUNT;
+ long duration = mDurations.getValue(key);
+ switch (procStateIndex) {
+ case STATE_TOP:
+ topMs += duration;
+ break;
+ case STATE_BOUND_TOP_OR_FGS:
+ boundTopMs += duration;
+ break;
+ case STATE_FGS:
+ fgsMs += duration;
+ break;
+ case STATE_IMPORTANT_FOREGROUND:
+ case STATE_IMPORTANT_BACKGROUND:
+ importantForegroundMs += duration;
+ break;
+ case STATE_BACKUP:
+ case STATE_SERVICE:
+ case STATE_SERVICE_RESTARTING:
+ case STATE_RECEIVER:
+ case STATE_HEAVY_WEIGHT:
+ case STATE_HOME:
+ case STATE_LAST_ACTIVITY:
+ case STATE_PERSISTENT:
+ otherMs += duration;
+ break;
+ case STATE_CACHED_ACTIVITY:
+ case STATE_CACHED_ACTIVITY_CLIENT:
+ case STATE_CACHED_EMPTY:
+ cachedMs += duration;
+ break;
+ // TODO (b/261910877) Add support for tracking boundFgsMs and
+ // frozenMs.
+ }
+ }
+ statsEventOutput.write(
+ atomTag,
+ getUid(),
+ getName(),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(processStats.mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ processStats.mTimePeriodEndUptime
+ - processStats.mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(topMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(fgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundTopMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(boundFgsMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(importantForegroundMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(cachedMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(frozenMs),
+ (int) TimeUnit.MILLISECONDS.toSeconds(otherMs));
+ }
+
/** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto, long fieldId,
String procName, int uid, long now,
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index d2b2f0a2b894..f3ed09a861e3 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -43,6 +43,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.procstats.AssociationState.SourceKey;
import com.android.internal.app.procstats.AssociationState.SourceState;
+import com.android.internal.util.function.QuintConsumer;
import dalvik.system.VMRuntime;
@@ -56,6 +57,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -2389,6 +2392,79 @@ public final class ProcessStats implements Parcelable {
}
}
+ void forEachProcess(Consumer<ProcessState> consumer) {
+ final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+ for (int ip = 0, size = procMap.size(); ip < size; ip++) {
+ final SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final ProcessState processState = uids.valueAt(iu);
+ consumer.accept(processState);
+ }
+ }
+ }
+
+ void forEachAssociation(
+ QuintConsumer<AssociationState, Integer, String, SourceKey, SourceState> consumer) {
+ final ArrayMap<String, SparseArray<LongSparseArray<PackageState>>> pkgMap =
+ mPackages.getMap();
+ for (int ip = 0, size = pkgMap.size(); ip < size; ip++) {
+ final SparseArray<LongSparseArray<PackageState>> uids = pkgMap.valueAt(ip);
+ for (int iu = 0, uidsSize = uids.size(); iu < uidsSize; iu++) {
+ final int uid = uids.keyAt(iu);
+ final LongSparseArray<PackageState> versions = uids.valueAt(iu);
+ for (int iv = 0, versionsSize = versions.size(); iv < versionsSize; iv++) {
+ final PackageState state = versions.valueAt(iv);
+ for (int iasc = 0, ascSize = state.mAssociations.size();
+ iasc < ascSize;
+ iasc++) {
+ final String serviceName = state.mAssociations.keyAt(iasc);
+ final AssociationState asc = state.mAssociations.valueAt(iasc);
+ for (int is = 0, sourcesSize = asc.mSources.size();
+ is < sourcesSize;
+ is++) {
+ final SourceState src = asc.mSources.valueAt(is);
+ final SourceKey key = asc.mSources.keyAt(is);
+ consumer.accept(asc, uid, serviceName, key, src);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** Dumps the stats of all processes to statsEventOutput. */
+ public void dumpProcessState(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachProcess(
+ (processState) -> {
+ if (processState.isMultiPackage()
+ && processState.getCommonProcess() != processState) {
+ return;
+ }
+ processState.dumpStateDurationToStatsd(atomTag, this, statsEventOutput);
+ });
+ }
+
+ /** Dumps all process association data to statsEventOutput. */
+ public void dumpProcessAssociation(int atomTag, StatsEventOutput statsEventOutput) {
+ forEachAssociation(
+ (asc, serviceUid, serviceName, key, src) -> {
+ statsEventOutput.write(
+ atomTag,
+ key.mUid,
+ key.mProcess,
+ serviceUid,
+ serviceName,
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(mTimePeriodEndUptime),
+ (int)
+ TimeUnit.MILLISECONDS.toSeconds(
+ mTimePeriodEndUptime - mTimePeriodStartUptime),
+ (int) TimeUnit.MILLISECONDS.toSeconds(src.mDuration),
+ src.mActiveCount,
+ asc.getProcessName());
+ });
+ }
+
private void dumpProtoPreamble(ProtoOutputStream proto) {
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
diff --git a/core/java/com/android/internal/app/procstats/StatsEventOutput.java b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
new file mode 100644
index 000000000000..b2e405475a4e
--- /dev/null
+++ b/core/java/com/android/internal/app/procstats/StatsEventOutput.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 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.internal.app.procstats;
+
+import android.util.StatsEvent;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.List;
+
+/**
+ * A simple wrapper of FrameworkStatsLog.buildStatsEvent. This allows unit tests to mock out the
+ * dependency.
+ */
+public class StatsEventOutput {
+
+ List<StatsEvent> mOutput;
+
+ public StatsEventOutput(List<StatsEvent> output) {
+ mOutput = output;
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int uid,
+ String processName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int topSeconds,
+ int fgsSeconds,
+ int boundTopSeconds,
+ int boundFgsSeconds,
+ int importantForegroundSeconds,
+ int cachedSeconds,
+ int frozenSeconds,
+ int otherSeconds) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ uid,
+ processName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ topSeconds,
+ fgsSeconds,
+ boundTopSeconds,
+ boundFgsSeconds,
+ importantForegroundSeconds,
+ cachedSeconds,
+ frozenSeconds,
+ otherSeconds));
+ }
+
+ /** Writes the data to the output. */
+ public void write(
+ int atomTag,
+ int clientUid,
+ String processName,
+ int serviceUid,
+ String serviceName,
+ int measurementStartUptimeSecs,
+ int measurementEndUptimeSecs,
+ int measurementDurationUptimeSecs,
+ int activeDurationUptimeSecs,
+ int activeCount,
+ String serviceProcessName) {
+ mOutput.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ clientUid,
+ processName,
+ serviceUid,
+ serviceName,
+ measurementStartUptimeSecs,
+ measurementEndUptimeSecs,
+ measurementDurationUptimeSecs,
+ activeDurationUptimeSecs,
+ activeCount,
+ serviceProcessName));
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
new file mode 100644
index 000000000000..9b9a84b79da3
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/procstats/ProcessStatsTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 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.internal.app.procstats;
+
+import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+import org.mockito.Mock;
+
+import java.util.concurrent.TimeUnit;
+
+/** Provides test cases for ProcessStats. */
+public class ProcessStatsTest extends TestCase {
+
+ private static final String APP_1_PACKAGE_NAME = "com.android.testapp";
+ private static final int APP_1_UID = 5001;
+ private static final long APP_1_VERSION = 10;
+ private static final String APP_1_PROCESS_NAME = "com.android.testapp.p";
+ private static final String APP_1_SERVICE_NAME = "com.android.testapp.service";
+
+ private static final String APP_2_PACKAGE_NAME = "com.android.testapp2";
+ private static final int APP_2_UID = 5002;
+ private static final long APP_2_VERSION = 30;
+ private static final String APP_2_PROCESS_NAME = "com.android.testapp2.p";
+
+ private static final long NOW_MS = 123000;
+ private static final int DURATION_SECS = 6;
+
+ @Mock StatsEventOutput mStatsEventOutput;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ }
+
+ @SmallTest
+ public void testDumpProcessState() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processStats.getProcessStateLocked(
+ APP_2_PACKAGE_NAME, APP_2_UID, APP_2_VERSION, APP_2_PROCESS_NAME);
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testNonZeroProcessStateDuration() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ ProcessState processState =
+ processStats.getProcessStateLocked(
+ APP_1_PACKAGE_NAME, APP_1_UID, APP_1_VERSION, APP_1_PROCESS_NAME);
+ processState.setCombinedState(STATE_TOP, NOW_MS);
+ processState.commitStateTime(NOW_MS + TimeUnit.SECONDS.toMillis(DURATION_SECS));
+ processStats.dumpProcessState(FrameworkStatsLog.PROCESS_STATE, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_STATE),
+ eq(APP_1_UID),
+ eq(APP_1_PROCESS_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(DURATION_SECS),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(0));
+ }
+
+ @SmallTest
+ public void testDumpProcessAssociation() throws Exception {
+ ProcessStats processStats = new ProcessStats();
+ AssociationState associationState =
+ processStats.getAssociationStateLocked(
+ APP_1_PACKAGE_NAME,
+ APP_1_UID,
+ APP_1_VERSION,
+ APP_1_PROCESS_NAME,
+ APP_1_SERVICE_NAME);
+ AssociationState.SourceState sourceState =
+ associationState.startSource(APP_2_UID, APP_2_PROCESS_NAME, APP_2_PACKAGE_NAME);
+ sourceState.stop();
+ processStats.dumpProcessAssociation(
+ FrameworkStatsLog.PROCESS_ASSOCIATION, mStatsEventOutput);
+ verify(mStatsEventOutput)
+ .write(
+ eq(FrameworkStatsLog.PROCESS_ASSOCIATION),
+ eq(APP_2_UID),
+ eq(APP_2_PROCESS_NAME),
+ eq(APP_1_UID),
+ eq(APP_1_SERVICE_NAME),
+ anyInt(),
+ anyInt(),
+ eq(0),
+ eq(0),
+ eq(0),
+ eq(APP_1_PROCESS_NAME));
+ }
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b4b8cf9a9eab..43fb44ca02af 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -169,6 +169,7 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessStats;
+import com.android.internal.app.procstats.StatsEventOutput;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
import com.android.internal.os.KernelAllocationStats;
@@ -612,12 +613,19 @@ public class StatsPullAtomService extends SystemService {
}
case FrameworkStatsLog.PROC_STATS:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_ALL, atomTag, data);
+ return pullProcStatsLocked(atomTag, data);
}
case FrameworkStatsLog.PROC_STATS_PKG_PROC:
synchronized (mProcStatsLock) {
- return pullProcStatsLocked(ProcessStats.REPORT_PKG_PROC_STATS, atomTag,
- data);
+ return pullProcStatsLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_STATE:
+ synchronized (mProcStatsLock) {
+ return pullProcessStateLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.PROCESS_ASSOCIATION:
+ synchronized (mProcStatsLock) {
+ return pullProcessAssociationLocked(atomTag, data);
}
case FrameworkStatsLog.DISK_IO:
synchronized (mDiskIoLock) {
@@ -890,6 +898,8 @@ public class StatsPullAtomService extends SystemService {
registerNumFacesEnrolled();
registerProcStats();
registerProcStatsPkgProc();
+ registerProcessState();
+ registerProcessAssociation();
registerDiskIO();
registerPowerProfile();
registerProcessCpuTime();
@@ -2870,59 +2880,138 @@ public class StatsPullAtomService extends SystemService {
);
}
- private int pullProcStatsLocked(int section, int atomTag, List<StatsEvent> pulledData) {
+ private void registerProcessState() {
+ int tagId = FrameworkStatsLog.PROCESS_STATE;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ private void registerProcessAssociation() {
+ int tagId = FrameworkStatsLog.PROCESS_ASSOCIATION;
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl);
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private ProcessStats getStatsFromProcessStatsService(int atomTag) {
IProcessStats processStatsService = getIProcessStatsService();
if (processStatsService == null) {
- return StatsManager.PULL_SKIP;
+ return null;
}
-
final long token = Binder.clearCallingIdentity();
try {
// force procstats to flush & combine old files into one store
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
-
- ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
- for (int i = 0; i < protoStreams.length; i++) {
- protoStreams[i] = new ProtoOutputStream();
- }
-
+ long lastHighWaterMark = readProcStatsHighWaterMark(atomTag);
ProcessStats procStats = new ProcessStats(false);
// Force processStatsService to aggregate all in-storage and in-memory data.
- long highWaterMark = processStatsService.getCommittedStatsMerged(
- lastHighWaterMark, section, true, null, procStats);
- procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
-
- for (int i = 0; i < protoStreams.length; i++) {
- byte[] bytes = protoStreams[i].getBytes(); // cache the value
- if (bytes.length > 0) {
- pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, bytes,
- // This is a shard ID, and is specified in the metric definition to be
- // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE to
- // keep all the shards, as it thinks each shard is a different dimension
- // of data.
- i));
- }
- }
-
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
+ long highWaterMark =
+ processStatsService.getCommittedStatsMerged(
+ lastHighWaterMark,
+ ProcessStats.REPORT_ALL, // ignored since committedStats below is null.
+ true,
+ null, // committedStats
+ procStats);
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + lastHighWaterMark)
.delete();
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
+ new File(
+ mBaseDir.getAbsolutePath()
+ + "/"
+ + highWaterMarkFilePrefix(atomTag)
+ + "_"
+ + highWaterMark)
.createNewFile();
+ return procStats;
} catch (RemoteException | IOException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
- return StatsManager.PULL_SKIP;
+ return null;
} finally {
Binder.restoreCallingIdentity(token);
}
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcStatsLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ ProtoOutputStream[] protoStreams = new ProtoOutputStream[MAX_PROCSTATS_SHARDS];
+ for (int i = 0; i < protoStreams.length; i++) {
+ protoStreams[i] = new ProtoOutputStream();
+ }
+ procStats.dumpAggregatedProtoForStatsd(protoStreams, MAX_PROCSTATS_RAW_SHARD_SIZE);
+ for (int i = 0; i < protoStreams.length; i++) {
+ byte[] bytes = protoStreams[i].getBytes(); // cache the value
+ if (bytes.length > 0) {
+ pulledData.add(
+ FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ bytes,
+ // This is a shard ID, and is specified in the metric definition to
+ // be
+ // a dimension. This will result in statsd using RANDOM_ONE_SAMPLE
+ // to
+ // keep all the shards, as it thinks each shard is a different
+ // dimension
+ // of data.
+ i));
+ }
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessStateLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessState(atomTag, new StatsEventOutput(pulledData));
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ @GuardedBy("mProcStatsLock")
+ private int pullProcessAssociationLocked(int atomTag, List<StatsEvent> pulledData) {
+ ProcessStats procStats = getStatsFromProcessStatsService(atomTag);
+ if (procStats == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ procStats.dumpProcessAssociation(atomTag, new StatsEventOutput(pulledData));
return StatsManager.PULL_SUCCESS;
}
+ private String highWaterMarkFilePrefix(int atomTag) {
+ // For backward compatibility, use the legacy ProcessStats enum value as the prefix for
+ // PROC_STATS and PROC_STATS_PKG_PROC.
+ if (atomTag == FrameworkStatsLog.PROC_STATS) {
+ return String.valueOf(ProcessStats.REPORT_ALL);
+ }
+ if (atomTag == FrameworkStatsLog.PROC_STATS_PKG_PROC) {
+ return String.valueOf(ProcessStats.REPORT_PKG_PROC_STATS);
+ }
+ return "atom-" + atomTag;
+ }
+
// read high watermark for section
- private long readProcStatsHighWaterMark(int section) {
+ private long readProcStatsHighWaterMark(int atomTag) {
try {
- File[] files = mBaseDir.listFiles((d, name) -> {
- return name.toLowerCase().startsWith(String.valueOf(section) + '_');
- });
+ File[] files =
+ mBaseDir.listFiles(
+ (d, name) -> {
+ return name.toLowerCase()
+ .startsWith(highWaterMarkFilePrefix(atomTag) + '_');
+ });
if (files == null || files.length == 0) {
return 0;
}