Merge "Client logging changes for ProcessState and ProcessAssociation atoms."
This commit is contained in:
committed by
Android (Google) Code Review
commit
5f58bceaa6
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -170,6 +170,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;
|
||||
@@ -613,12 +614,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) {
|
||||
@@ -891,6 +899,8 @@ public class StatsPullAtomService extends SystemService {
|
||||
registerNumFacesEnrolled();
|
||||
registerProcStats();
|
||||
registerProcStatsPkgProc();
|
||||
registerProcessState();
|
||||
registerProcessAssociation();
|
||||
registerDiskIO();
|
||||
registerPowerProfile();
|
||||
registerProcessCpuTime();
|
||||
@@ -2884,59 +2894,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user