Pull process cpu stats into statsd
Here is a sample output:
$ adb shell cmd stats pull-source 10035
Pull from 10035: { 1539500981000000000 222067020557 (10035)0x10000->0[I]
0x20000->ksoftirqd/0[S] 0x30000->0[L] 0x40000->720[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->1000[I]
0x20000->android.hardware.graphics.composer@2.1-service[S]
0x30000->1390[L] 0x40000->2240[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->1002[I]
0x20000->android.hardware.bluetooth@1.0-service-qti[S] 0x30000->50[L]
0x40000->80[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->1010[I] 0x20000->android.hardware.wifi@1.0-service[S]
0x30000->80[L] 0x40000->150[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->1069[I] 0x20000->lmkd[S] 0x30000->60[L] 0x40000->280[L]
}
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->9999[I] 0x20000->traced_probes[S] 0x30000->0[L]
0x40000->10[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->1066[I] 0x20000->statsd[S] 0x30000->160[L]
0x40000->160[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10024[I] 0x20000->com.android.systemui[S]
0x30000->3020[L] 0x40000->740[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10058[I] 0x20000->com.ustwo.lwp[S] 0x30000->9120[L]
0x40000->7810[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10080[I] 0x20000->com.google.android.apps.turbo[S]
0x30000->410[L] 0x40000->150[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10085[I] 0x20000->com.google.android.gms.persistent[S]
0x30000->9890[L] 0x40000->2560[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10110[I] 0x20000->com.google.android.ims[S]
0x30000->530[L] 0x40000->210[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10097[I] 0x20000->com.google.android.apps.maps[S]
0x30000->1170[L] 0x40000->290[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10014[I] 0x20000->android.process.acore[S]
0x30000->500[L] 0x40000->180[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->10131[I] 0x20000->com.google.android.contacts[S]
0x30000->270[L] 0x40000->160[L] }
Pull from 10035: { 1539500981000000000 222067020557
(10035)0x10000->2000[I] 0x20000->cmd[S] 0x30000->20[L] 0x40000->60[L] }
Bug: 113353129
Test: will add cts
Change-Id: Ia5335910e4f044791e9043823cc4f007d372e7d3
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 4604510..4045996 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -183,6 +183,7 @@
DiskIo disk_io = 10032;
PowerProfile power_profile = 10033;
ProcStats proc_stats_pkg_proc = 10034;
+ ProcessCpuTime process_cpu_time = 10035;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -3006,3 +3007,19 @@
message PowerProfile {
optional PowerProfileProto power_profile = 1;
}
+
+/**
+ * Pulls process user time and system time. Puller takes a snapshot of all pids
+ * in the system and returns cpu stats for those that are working at the time.
+ * Dead pids will be dropped. Kernel processes are excluded.
+ * Min cool-down is 5 sec.
+ */
+message ProcessCpuTime {
+ optional int32 uid = 1 [(is_uid) = true];
+
+ optional string process_name = 2;
+ // Process cpu time in user space, cumulative from boot/process start
+ optional int64 user_time_millis = 3;
+ // Process cpu time in system space, cumulative from boot/process start
+ optional int64 system_time_millis = 4;
+}
\ No newline at end of file
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index dab64ca..4c74c17 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -223,6 +223,9 @@
// PowerProfile constants for power model calculations.
{android::util::POWER_PROFILE,
{{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
+ // Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
+ {android::util::PROCESS_CPU_TIME,
+ {{}, {}, 5 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 6ca4f2e..13c6638 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -85,6 +85,7 @@
import com.android.internal.os.KernelWakelockStats;
import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
+import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
@@ -164,11 +165,6 @@
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
private IWifiManager mWifiManager = null;
private TelephonyManager mTelephony = null;
- private final StatFs mStatFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
- private final StatFs mStatFsSystem =
- new StatFs(Environment.getRootDirectory().getAbsolutePath());
- private final StatFs mStatFsTemp =
- new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@GuardedBy("sStatsdLock")
private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
@GuardedBy("sStatsdLock")
@@ -188,6 +184,8 @@
private static IThermalService sThermalService;
private File mBaseDir =
new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
+ @GuardedBy("this")
+ ProcessCpuTracker mProcessCpuTracker = null;
public StatsCompanionService(Context context) {
super();
@@ -756,7 +754,7 @@
private void pullBluetoothBytesTransfer(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = pullBluetoothData();
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
if (info.getUidTraffic() != null) {
for (UidTraffic traffic : info.getUidTraffic()) {
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
@@ -868,9 +866,12 @@
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- if (mWifiManager == null) {
- mWifiManager =
- IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
+ synchronized (this) {
+ if (mWifiManager == null) {
+ mWifiManager =
+ IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ }
}
if (mWifiManager != null) {
try {
@@ -900,8 +901,10 @@
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
long token = Binder.clearCallingIdentity();
- if (mTelephony == null) {
- mTelephony = TelephonyManager.from(mContext);
+ synchronized (this) {
+ if (mTelephony == null) {
+ mTelephony = TelephonyManager.from(mContext);
+ }
}
if (mTelephony != null) {
SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -925,7 +928,7 @@
private void pullBluetoothActivityInfo(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- BluetoothActivityEnergyInfo info = pullBluetoothData();
+ BluetoothActivityEnergyInfo info = fetchBluetoothData();
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
e.writeLong(info.getTimeStamp());
e.writeInt(info.getBluetoothStackState());
@@ -936,7 +939,7 @@
pulledData.add(e);
}
- private synchronized BluetoothActivityEnergyInfo pullBluetoothData() {
+ private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
@@ -1290,30 +1293,35 @@
private void pullProcessStats(int section, int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- try {
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
- List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
- long highWaterMark = mProcessStats.getCommittedStats(
- lastHighWaterMark, section, true, statsFiles);
- if (statsFiles.size() != 1) {
- return;
+ synchronized (this) {
+ try {
+ long lastHighWaterMark = readProcStatsHighWaterMark(section);
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ long highWaterMark = mProcessStats.getCommittedStats(
+ lastHighWaterMark, section, true, statsFiles);
+ if (statsFiles.size() != 1) {
+ return;
+ }
+ InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ statsFiles.get(0));
+ int[] len = new int[1];
+ byte[] stats = readFully(stream, len);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+ wallClockNanos);
+ e.writeStorage(Arrays.copyOf(stats, len[0]));
+ pulledData.add(e);
+ new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
+ + lastHighWaterMark).delete();
+ new File(
+ mBaseDir.getAbsolutePath() + "/" + section + "_"
+ + highWaterMark).createNewFile();
+ } catch (IOException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Getting procstats failed: ", e);
}
- InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
- int[] len = new int[1];
- byte[] stats = readFully(stream, len);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeStorage(Arrays.copyOf(stats, len[0]));
- pulledData.add(e);
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark).delete();
- new File(
- mBaseDir.getAbsolutePath() + "/" + section + "_"
- + highWaterMark).createNewFile();
- } catch (IOException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Getting procstats failed: ", e);
}
}
@@ -1382,12 +1390,34 @@
});
}
+ private void pullProcessCpuTime(int tagId, long elapsedNanos, final long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ synchronized (this) {
+ if (mProcessCpuTracker == null) {
+ mProcessCpuTracker = new ProcessCpuTracker(false);
+ mProcessCpuTracker.init();
+ }
+ mProcessCpuTracker.update();
+ for (int i = 0; i < mProcessCpuTracker.countStats(); i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+ wallClockNanos);
+ e.writeInt(st.uid);
+ e.writeString(st.name);
+ e.writeLong(st.base_utime);
+ e.writeLong(st.base_stime);
+ pulledData.add(e);
+ }
+ }
+ }
+
/**
* Pulls various data.
*/
@Override // Binder call
public StatsLogEventWrapper[] pullData(int tagId) {
enforceCallingPermission();
+
if (DEBUG) {
Slog.d(TAG, "Pulling " + tagId);
}
@@ -1496,7 +1526,8 @@
break;
}
case StatsLog.PROC_STATS: {
- pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos, ret);
+ pullProcessStats(ProcessStats.REPORT_ALL, tagId, elapsedNanos, wallClockNanos,
+ ret);
break;
}
case StatsLog.PROC_STATS_PKG_PROC: {
@@ -1512,6 +1543,10 @@
pullPowerProfile(tagId, elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.PROCESS_CPU_TIME: {
+ pullProcessCpuTime(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;