blob: c10d81b96cbcfe49e8842647ce8da6c4a483fb9e [file] [log] [blame]
Dianne Hackbornd2932242013-08-05 18:18:42 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Dianne Hackborn8a0de582013-08-07 15:22:07 -070019import android.content.pm.PackageManager;
20import android.os.Binder;
Dianne Hackbornd2932242013-08-05 18:18:42 -070021import android.os.Parcel;
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070022import android.os.ParcelFileDescriptor;
Dianne Hackbornd2932242013-08-05 18:18:42 -070023import android.os.RemoteException;
24import android.os.SystemClock;
25import android.os.SystemProperties;
Yi Jin9680cfa2017-09-15 15:14:43 -070026import android.service.procstats.ProcessStatsProto;
27import android.service.procstats.ProcessStatsServiceDumpProto;
Dianne Hackbornd2932242013-08-05 18:18:42 -070028import android.util.ArrayMap;
29import android.util.AtomicFile;
Dianne Hackborn3accca02013-09-20 09:32:11 -070030import android.util.LongSparseArray;
Dianne Hackbornd2932242013-08-05 18:18:42 -070031import android.util.Slog;
32import android.util.SparseArray;
Dianne Hackborn53459a72013-09-17 17:14:57 -070033import android.util.TimeUtils;
Yi Jin9680cfa2017-09-15 15:14:43 -070034import android.util.proto.ProtoOutputStream;
Makoto Onuki3ed5be32017-02-01 14:04:47 -080035
36import com.android.internal.annotations.GuardedBy;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070037import com.android.internal.app.procstats.DumpUtils;
38import com.android.internal.app.procstats.IProcessStats;
39import com.android.internal.app.procstats.ProcessState;
40import com.android.internal.app.procstats.ProcessStats;
41import com.android.internal.app.procstats.ServiceState;
Dianne Hackbornd2932242013-08-05 18:18:42 -070042import com.android.internal.os.BackgroundThread;
43
44import java.io.File;
45import java.io.FileDescriptor;
46import java.io.FileInputStream;
47import java.io.FileOutputStream;
48import java.io.IOException;
Dianne Hackborn53459a72013-09-17 17:14:57 -070049import java.io.InputStream;
Dianne Hackbornd2932242013-08-05 18:18:42 -070050import java.io.PrintWriter;
51import java.util.ArrayList;
52import java.util.Collections;
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070053import java.util.List;
Dianne Hackbornd2932242013-08-05 18:18:42 -070054import java.util.concurrent.locks.ReentrantLock;
55
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070056public final class ProcessStatsService extends IProcessStats.Stub {
Dianne Hackbornd2932242013-08-05 18:18:42 -070057 static final String TAG = "ProcessStatsService";
58 static final boolean DEBUG = false;
59
60 // Most data is kept in a sparse data structure: an integer array which integer
61 // holds the type of the entry, and the identifier for a long array that data
62 // exists in and the offset into the array to find it. The constants below
63 // define the encoding of that data in an integer.
64
Dianne Hackborn6d9ef382013-09-23 14:39:23 -070065 static final int MAX_HISTORIC_STATES = 8; // Maximum number of historic states we will keep.
Dianne Hackbornd2932242013-08-05 18:18:42 -070066 static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames.
67 static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames.
68 static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in.
69 static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
Dianne Hackbornd2932242013-08-05 18:18:42 -070070
Dianne Hackborn8a0de582013-08-07 15:22:07 -070071 final ActivityManagerService mAm;
Dianne Hackbornd2932242013-08-05 18:18:42 -070072 final File mBaseDir;
73 ProcessStats mProcessStats;
74 AtomicFile mFile;
75 boolean mCommitPending;
76 boolean mShuttingDown;
77 int mLastMemOnlyState = -1;
78 boolean mMemFactorLowered;
79
80 final ReentrantLock mWriteLock = new ReentrantLock();
81 final Object mPendingWriteLock = new Object();
82 AtomicFile mPendingWriteFile;
83 Parcel mPendingWrite;
84 boolean mPendingWriteCommitted;
85 long mLastWriteTime;
86
Makoto Onuki3ed5be32017-02-01 14:04:47 -080087 /** For CTS to inject the screen state. */
88 @GuardedBy("mAm")
89 Boolean mInjectedScreenState;
90
Dianne Hackborn8a0de582013-08-07 15:22:07 -070091 public ProcessStatsService(ActivityManagerService am, File file) {
92 mAm = am;
Dianne Hackbornd2932242013-08-05 18:18:42 -070093 mBaseDir = file;
94 mBaseDir.mkdirs();
95 mProcessStats = new ProcessStats(true);
96 updateFile();
97 SystemProperties.addChangeCallback(new Runnable() {
98 @Override public void run() {
Dianne Hackborn8a0de582013-08-07 15:22:07 -070099 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700100 if (mProcessStats.evaluateSystemProperties(false)) {
101 mProcessStats.mFlags |= ProcessStats.FLAG_SYSPROPS;
102 writeStateLocked(true, true);
103 mProcessStats.evaluateSystemProperties(true);
104 }
105 }
106 }
107 });
108 }
109
Dianne Hackbornd94d5332013-10-03 17:32:19 -0700110 @Override
111 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
112 throws RemoteException {
113 try {
114 return super.onTransact(code, data, reply, flags);
115 } catch (RuntimeException e) {
116 if (!(e instanceof SecurityException)) {
117 Slog.wtf(TAG, "Process Stats Crash", e);
118 }
119 throw e;
120 }
121 }
122
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700123 public ProcessState getProcessStateLocked(String packageName,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700124 int uid, long versionCode, String processName) {
Dianne Hackborn8472e612014-01-23 17:57:20 -0800125 return mProcessStats.getProcessStateLocked(packageName, uid, versionCode, processName);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700126 }
127
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700128 public ServiceState getServiceStateLocked(String packageName, int uid,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700129 long versionCode, String processName, String className) {
Dianne Hackborn8472e612014-01-23 17:57:20 -0800130 return mProcessStats.getServiceStateLocked(packageName, uid, versionCode, processName,
131 className);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700132 }
133
134 public boolean isMemFactorLowered() {
135 return mMemFactorLowered;
136 }
137
Andreas Gampea36dc622018-02-05 17:19:22 -0800138 @GuardedBy("mAm")
Dianne Hackbornd2932242013-08-05 18:18:42 -0700139 public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
140 mMemFactorLowered = memFactor < mLastMemOnlyState;
141 mLastMemOnlyState = memFactor;
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800142 if (mInjectedScreenState != null) {
143 screenOn = mInjectedScreenState;
144 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700145 if (screenOn) {
146 memFactor += ProcessStats.ADJ_SCREEN_ON;
147 }
148 if (memFactor != mProcessStats.mMemFactor) {
149 if (mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING) {
150 mProcessStats.mMemFactorDurations[mProcessStats.mMemFactor]
151 += now - mProcessStats.mStartTime;
152 }
153 mProcessStats.mMemFactor = memFactor;
154 mProcessStats.mStartTime = now;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700155 final ArrayMap<String, SparseArray<LongSparseArray<ProcessStats.PackageState>>> pmap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700156 = mProcessStats.mPackages.getMap();
Dianne Hackborn8472e612014-01-23 17:57:20 -0800157 for (int ipkg=pmap.size()-1; ipkg>=0; ipkg--) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700158 final SparseArray<LongSparseArray<ProcessStats.PackageState>> uids =
159 pmap.valueAt(ipkg);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800160 for (int iuid=uids.size()-1; iuid>=0; iuid--) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700161 final LongSparseArray<ProcessStats.PackageState> vers = uids.valueAt(iuid);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800162 for (int iver=vers.size()-1; iver>=0; iver--) {
163 final ProcessStats.PackageState pkg = vers.valueAt(iver);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700164 final ArrayMap<String, ServiceState> services = pkg.mServices;
Dianne Hackborn8472e612014-01-23 17:57:20 -0800165 for (int isvc=services.size()-1; isvc>=0; isvc--) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700166 final ServiceState service = services.valueAt(isvc);
167 service.setMemFactor(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700168 }
169 }
170 }
171 }
172 return true;
173 }
174 return false;
175 }
176
177 public int getMemFactorLocked() {
178 return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0;
179 }
180
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700181 public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem,
182 long nativeMem) {
183 mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem);
184 }
185
Dianne Hackbornd2932242013-08-05 18:18:42 -0700186 public boolean shouldWriteNowLocked(long now) {
187 if (now > (mLastWriteTime+WRITE_PERIOD)) {
188 if (SystemClock.elapsedRealtime()
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700189 > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD) &&
190 SystemClock.uptimeMillis()
191 > (mProcessStats.mTimePeriodStartUptime+ProcessStats.COMMIT_UPTIME_PERIOD)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700192 mCommitPending = true;
193 }
194 return true;
195 }
196 return false;
197 }
198
199 public void shutdownLocked() {
200 Slog.w(TAG, "Writing process stats before shutdown...");
201 mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN;
202 writeStateSyncLocked();
203 mShuttingDown = true;
204 }
205
206 public void writeStateAsyncLocked() {
207 writeStateLocked(false);
208 }
209
210 public void writeStateSyncLocked() {
211 writeStateLocked(true);
212 }
213
214 private void writeStateLocked(boolean sync) {
215 if (mShuttingDown) {
216 return;
217 }
218 boolean commitPending = mCommitPending;
219 mCommitPending = false;
220 writeStateLocked(sync, commitPending);
221 }
222
223 public void writeStateLocked(boolean sync, final boolean commit) {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800224 final long totalTime;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700225 synchronized (mPendingWriteLock) {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800226 final long now = SystemClock.uptimeMillis();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700227 if (mPendingWrite == null || !mPendingWriteCommitted) {
228 mPendingWrite = Parcel.obtain();
229 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700230 mProcessStats.mTimePeriodEndUptime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700231 if (commit) {
232 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
233 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700234 mProcessStats.writeToParcel(mPendingWrite, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700235 mPendingWriteFile = new AtomicFile(mFile.getBaseFile());
236 mPendingWriteCommitted = commit;
237 }
238 if (commit) {
239 mProcessStats.resetSafely();
240 updateFile();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800241 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700242 }
243 mLastWriteTime = SystemClock.uptimeMillis();
Dianne Hackborne17b4452018-01-10 13:15:40 -0800244 totalTime = SystemClock.uptimeMillis() - now;
245 if (DEBUG) Slog.d(TAG, "Prepared write state in " + now + "ms");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700246 if (!sync) {
247 BackgroundThread.getHandler().post(new Runnable() {
248 @Override public void run() {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800249 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700250 }
251 });
252 return;
253 }
254 }
255
Dianne Hackborne17b4452018-01-10 13:15:40 -0800256 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700257 }
258
259 private void updateFile() {
260 mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX
261 + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
262 mLastWriteTime = SystemClock.uptimeMillis();
263 }
264
Dianne Hackborne17b4452018-01-10 13:15:40 -0800265 void performWriteState(long initialTime) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700266 if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
267 Parcel data;
268 AtomicFile file;
269 synchronized (mPendingWriteLock) {
270 data = mPendingWrite;
271 file = mPendingWriteFile;
272 mPendingWriteCommitted = false;
273 if (data == null) {
274 return;
275 }
276 mPendingWrite = null;
277 mPendingWriteFile = null;
278 mWriteLock.lock();
279 }
280
Dianne Hackborne17b4452018-01-10 13:15:40 -0800281 final long startTime = SystemClock.uptimeMillis();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700282 FileOutputStream stream = null;
283 try {
284 stream = file.startWrite();
285 stream.write(data.marshall());
286 stream.flush();
287 file.finishWrite(stream);
Dianne Hackborne17b4452018-01-10 13:15:40 -0800288 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
289 "procstats", SystemClock.uptimeMillis() - startTime + initialTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700290 if (DEBUG) Slog.d(TAG, "Write completed successfully!");
291 } catch (IOException e) {
292 Slog.w(TAG, "Error writing process statistics", e);
293 file.failWrite(stream);
294 } finally {
295 data.recycle();
296 trimHistoricStatesWriteLocked();
297 mWriteLock.unlock();
298 }
299 }
300
Dianne Hackbornd2932242013-08-05 18:18:42 -0700301 boolean readLocked(ProcessStats stats, AtomicFile file) {
302 try {
303 FileInputStream stream = file.openRead();
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700304 stats.read(stream);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700305 stream.close();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700306 if (stats.mReadError != null) {
307 Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
308 if (DEBUG) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700309 ArrayMap<String, SparseArray<ProcessState>> procMap = stats.mProcesses.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700310 final int NPROC = procMap.size();
311 for (int ip=0; ip<NPROC; ip++) {
312 Slog.w(TAG, "Process: " + procMap.keyAt(ip));
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700313 SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700314 final int NUID = uids.size();
315 for (int iu=0; iu<NUID; iu++) {
316 Slog.w(TAG, " Uid " + uids.keyAt(iu) + ": " + uids.valueAt(iu));
317 }
318 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700319 ArrayMap<String, SparseArray<LongSparseArray<ProcessStats.PackageState>>> pkgMap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700320 = stats.mPackages.getMap();
321 final int NPKG = pkgMap.size();
322 for (int ip=0; ip<NPKG; ip++) {
323 Slog.w(TAG, "Package: " + pkgMap.keyAt(ip));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700324 SparseArray<LongSparseArray<ProcessStats.PackageState>> uids
Dianne Hackborn8472e612014-01-23 17:57:20 -0800325 = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700326 final int NUID = uids.size();
327 for (int iu=0; iu<NUID; iu++) {
328 Slog.w(TAG, " Uid: " + uids.keyAt(iu));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700329 LongSparseArray<ProcessStats.PackageState> vers = uids.valueAt(iu);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800330 final int NVERS = vers.size();
331 for (int iv=0; iv<NVERS; iv++) {
332 Slog.w(TAG, " Vers: " + vers.keyAt(iv));
333 ProcessStats.PackageState pkgState = vers.valueAt(iv);
334 final int NPROCS = pkgState.mProcesses.size();
335 for (int iproc=0; iproc<NPROCS; iproc++) {
336 Slog.w(TAG, " Process " + pkgState.mProcesses.keyAt(iproc)
337 + ": " + pkgState.mProcesses.valueAt(iproc));
338 }
339 final int NSRVS = pkgState.mServices.size();
340 for (int isvc=0; isvc<NSRVS; isvc++) {
341 Slog.w(TAG, " Service " + pkgState.mServices.keyAt(isvc)
342 + ": " + pkgState.mServices.valueAt(isvc));
343
344 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700345 }
346 }
347 }
348 }
349 return false;
350 }
351 } catch (Throwable e) {
352 stats.mReadError = "caught exception: " + e;
353 Slog.e(TAG, "Error reading process statistics", e);
354 return false;
355 }
356 return true;
357 }
358
Dianne Hackborn53459a72013-09-17 17:14:57 -0700359 private ArrayList<String> getCommittedFiles(int minNum, boolean inclCurrent,
360 boolean inclCheckedIn) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700361 File[] files = mBaseDir.listFiles();
362 if (files == null || files.length <= minNum) {
363 return null;
364 }
365 ArrayList<String> filesArray = new ArrayList<String>(files.length);
366 String currentFile = mFile.getBaseFile().getPath();
367 if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
368 for (int i=0; i<files.length; i++) {
369 File file = files[i];
370 String fileStr = file.getPath();
371 if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700372 if (!inclCheckedIn && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700373 if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
374 continue;
375 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700376 if (!inclCurrent && fileStr.equals(currentFile)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700377 if (DEBUG) Slog.d(TAG, "Skipping: current stats");
378 continue;
379 }
380 filesArray.add(fileStr);
381 }
382 Collections.sort(filesArray);
383 return filesArray;
384 }
385
386 public void trimHistoricStatesWriteLocked() {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700387 ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700388 if (filesArray == null) {
389 return;
390 }
391 while (filesArray.size() > MAX_HISTORIC_STATES) {
392 String file = filesArray.remove(0);
393 Slog.i(TAG, "Pruning old procstats: " + file);
394 (new File(file)).delete();
395 }
396 }
397
398 boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
399 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
400 boolean sepProcStates, int[] procStates, long now, String reqPackage) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700401 ArrayList<ProcessState> procs = mProcessStats.collectProcessesLocked(
Dianne Hackborn164371f2013-10-01 19:10:13 -0700402 screenStates, memStates, procStates, procStates, now, reqPackage, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700403 if (procs.size() > 0) {
404 if (header != null) {
405 pw.println(header);
406 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700407 DumpUtils.dumpProcessListCsv(pw, procs, sepScreenStates, screenStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700408 sepMemStates, memStates, sepProcStates, procStates, now);
409 return true;
410 }
411 return false;
412 }
413
414 static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
415 String[] outError) {
416 ArrayList<Integer> res = new ArrayList<Integer>();
417 int lastPos = 0;
418 for (int i=0; i<=arg.length(); i++) {
419 char c = i < arg.length() ? arg.charAt(i) : 0;
420 if (c != ',' && c != '+' && c != ' ' && c != 0) {
421 continue;
422 }
423 boolean isSep = c == ',';
424 if (lastPos == 0) {
425 // We now know the type of op.
426 outSep[0] = isSep;
427 } else if (c != 0 && outSep[0] != isSep) {
428 outError[0] = "inconsistent separators (can't mix ',' with '+')";
429 return null;
430 }
431 if (lastPos < (i-1)) {
432 String str = arg.substring(lastPos, i);
433 for (int j=0; j<states.length; j++) {
434 if (str.equals(states[j])) {
435 res.add(j);
436 str = null;
437 break;
438 }
439 }
440 if (str != null) {
441 outError[0] = "invalid word \"" + str + "\"";
442 return null;
443 }
444 }
445 lastPos = i + 1;
446 }
447
448 int[] finalRes = new int[res.size()];
449 for (int i=0; i<res.size(); i++) {
450 finalRes[i] = res.get(i) * mult;
451 }
452 return finalRes;
453 }
454
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700455 public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700456 mAm.mContext.enforceCallingOrSelfPermission(
457 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700458 Parcel current = Parcel.obtain();
riddle_hsu61231a52014-11-15 18:40:08 +0800459 synchronized (mAm) {
460 long now = SystemClock.uptimeMillis();
461 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
462 mProcessStats.mTimePeriodEndUptime = now;
463 mProcessStats.writeToParcel(current, now, 0);
464 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700465 mWriteLock.lock();
466 try {
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700467 if (historic != null) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700468 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700469 if (files != null) {
470 for (int i=files.size()-1; i>=0; i--) {
471 try {
472 ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
473 new File(files.get(i)), ParcelFileDescriptor.MODE_READ_ONLY);
474 historic.add(pfd);
475 } catch (IOException e) {
476 Slog.w(TAG, "Failure opening procstat file " + files.get(i), e);
477 }
478 }
479 }
480 }
481 } finally {
482 mWriteLock.unlock();
483 }
484 return current.marshall();
485 }
486
Dianne Hackborn53459a72013-09-17 17:14:57 -0700487 public ParcelFileDescriptor getStatsOverTime(long minTime) {
488 mAm.mContext.enforceCallingOrSelfPermission(
489 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
riddle_hsu61231a52014-11-15 18:40:08 +0800490 Parcel current = Parcel.obtain();
491 long curTime;
492 synchronized (mAm) {
493 long now = SystemClock.uptimeMillis();
494 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
495 mProcessStats.mTimePeriodEndUptime = now;
496 mProcessStats.writeToParcel(current, now, 0);
497 curTime = mProcessStats.mTimePeriodEndRealtime
498 - mProcessStats.mTimePeriodStartRealtime;
499 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700500 mWriteLock.lock();
501 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700502 if (curTime < minTime) {
503 // Need to add in older stats to reach desired time.
504 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborncb428552013-09-26 11:07:17 -0700505 if (files != null && files.size() > 0) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700506 current.setDataPosition(0);
507 ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current);
508 current.recycle();
Dianne Hackborn59da6792013-10-10 18:27:24 -0700509 int i = files.size()-1;
510 while (i >= 0 && (stats.mTimePeriodEndRealtime
Dianne Hackborn53459a72013-09-17 17:14:57 -0700511 - stats.mTimePeriodStartRealtime) < minTime) {
512 AtomicFile file = new AtomicFile(new File(files.get(i)));
Dianne Hackborn59da6792013-10-10 18:27:24 -0700513 i--;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700514 ProcessStats moreStats = new ProcessStats(false);
515 readLocked(moreStats, file);
516 if (moreStats.mReadError == null) {
517 stats.add(moreStats);
518 StringBuilder sb = new StringBuilder();
519 sb.append("Added stats: ");
520 sb.append(moreStats.mTimePeriodStartClockStr);
521 sb.append(", over ");
522 TimeUtils.formatDuration(moreStats.mTimePeriodEndRealtime
523 - moreStats.mTimePeriodStartRealtime, sb);
524 Slog.i(TAG, sb.toString());
525 } else {
Dianne Hackborn59da6792013-10-10 18:27:24 -0700526 Slog.w(TAG, "Failure reading " + files.get(i+1) + "; "
Dianne Hackborn53459a72013-09-17 17:14:57 -0700527 + moreStats.mReadError);
528 continue;
529 }
530 }
531 current = Parcel.obtain();
532 stats.writeToParcel(current, 0);
533 }
534 }
535 final byte[] outData = current.marshall();
536 current.recycle();
537 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
538 Thread thr = new Thread("ProcessStats pipe output") {
539 public void run() {
540 FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]);
541 try {
542 fout.write(outData);
543 fout.close();
544 } catch (IOException e) {
545 Slog.w(TAG, "Failure writing pipe", e);
546 }
547 }
548 };
549 thr.start();
550 return fds[0];
551 } catch (IOException e) {
552 Slog.w(TAG, "Failed building output pipe", e);
553 } finally {
554 mWriteLock.unlock();
555 }
556 return null;
557 }
558
Dianne Hackborn69cb00b2013-08-09 16:16:56 -0700559 public int getCurrentMemoryState() {
560 synchronized (mAm) {
561 return mLastMemOnlyState;
562 }
563 }
564
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700565 private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
566 String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
567 boolean dumpAll, boolean activeOnly) {
568 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
569 - (ProcessStats.COMMIT_PERIOD/2));
570 if (pfd == null) {
571 pw.println("Unable to build stats!");
572 return;
573 }
574 ProcessStats stats = new ProcessStats(false);
575 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
576 stats.read(stream);
577 if (stats.mReadError != null) {
578 pw.print("Failure reading: "); pw.println(stats.mReadError);
579 return;
580 }
581 if (isCompact) {
582 stats.dumpCheckinLocked(pw, reqPackage);
583 } else {
584 if (dumpDetails || dumpFullDetails) {
585 stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
586 } else {
587 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
588 }
589 }
590 }
591
Dianne Hackbornd2932242013-08-05 18:18:42 -0700592 static private void dumpHelp(PrintWriter pw) {
593 pw.println("Process stats (procstats) dump options:");
594 pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700595 pw.println(" [--details] [--full-details] [--current] [--hours N] [--last N]");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800596 pw.println(" [--max N] --active] [--commit] [--reset] [--clear] [--write] [-h]");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800597 pw.println(" [--start-testing] [--stop-testing] ");
598 pw.println(" [--pretend-screen-on] [--pretend-screen-off] [--stop-pretend-screen]");
599 pw.println(" [<package.name>]");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700600 pw.println(" --checkin: perform a checkin: print and delete old committed states.");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800601 pw.println(" -c: print only state in checkin format.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700602 pw.println(" --csv: output data suitable for putting in a spreadsheet.");
603 pw.println(" --csv-screen: on, off.");
604 pw.println(" --csv-mem: norm, mod, low, crit.");
605 pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
606 pw.println(" service, home, prev, cached");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700607 pw.println(" --details: dump per-package details, not just summary.");
608 pw.println(" --full-details: dump all timing and active state details.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700609 pw.println(" --current: only dump current state.");
Dianne Hackborncb428552013-09-26 11:07:17 -0700610 pw.println(" --hours: aggregate over about N last hours.");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700611 pw.println(" --last: only show the last committed stats at index N (starting at 1).");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800612 pw.println(" --max: for -a, max num of historical batches to print.");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700613 pw.println(" --active: only show currently active processes/services.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700614 pw.println(" --commit: commit current stats to disk and reset to start new stats.");
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700615 pw.println(" --reset: reset current stats, without committing.");
Dianne Hackborn53459a72013-09-17 17:14:57 -0700616 pw.println(" --clear: clear all stats; does both --reset and deletes old stats.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700617 pw.println(" --write: write current in-memory stats to disk.");
618 pw.println(" --read: replace current stats with last-written stats.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800619 pw.println(" --start-testing: clear all stats and starting high frequency pss sampling.");
620 pw.println(" --stop-testing: stop high frequency pss sampling.");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800621 pw.println(" --pretend-screen-on: pretend screen is on.");
622 pw.println(" --pretend-screen-off: pretend screen is off.");
623 pw.println(" --stop-pretend-screen: forget \"pretend screen\" and use the real state.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700624 pw.println(" -a: print everything.");
625 pw.println(" -h: print this help text.");
626 pw.println(" <package.name>: optional name of package to filter output by.");
627 }
628
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700629 @Override
630 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -0600631 if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600632 TAG, pw)) return;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700633
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700634 long ident = Binder.clearCallingIdentity();
635 try {
Yi Jin9680cfa2017-09-15 15:14:43 -0700636 if (args.length > 0 && "--proto".equals(args[0])) {
637 dumpProto(fd);
638 } else {
639 dumpInner(pw, args);
640 }
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700641 } finally {
642 Binder.restoreCallingIdentity(ident);
643 }
644 }
645
Yi Jin9680cfa2017-09-15 15:14:43 -0700646 private void dumpInner(PrintWriter pw, String[] args) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700647 final long now = SystemClock.uptimeMillis();
648
649 boolean isCheckin = false;
650 boolean isCompact = false;
651 boolean isCsv = false;
652 boolean currentOnly = false;
653 boolean dumpDetails = false;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700654 boolean dumpFullDetails = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700655 boolean dumpAll = false;
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800656 boolean quit = false;
Dianne Hackborncb428552013-09-26 11:07:17 -0700657 int aggregateHours = 0;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700658 int lastIndex = 0;
Dianne Hackbornd052a942014-11-21 15:23:13 -0800659 int maxNum = 2;
Dianne Hackborn164371f2013-10-01 19:10:13 -0700660 boolean activeOnly = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700661 String reqPackage = null;
662 boolean csvSepScreenStats = false;
663 int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
664 boolean csvSepMemStats = false;
665 int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL};
666 boolean csvSepProcStats = true;
667 int[] csvProcStats = ProcessStats.ALL_PROC_STATES;
668 if (args != null) {
669 for (int i=0; i<args.length; i++) {
670 String arg = args[i];
671 if ("--checkin".equals(arg)) {
672 isCheckin = true;
673 } else if ("-c".equals(arg)) {
674 isCompact = true;
675 } else if ("--csv".equals(arg)) {
676 isCsv = true;
677 } else if ("--csv-screen".equals(arg)) {
678 i++;
679 if (i >= args.length) {
680 pw.println("Error: argument required for --csv-screen");
681 dumpHelp(pw);
682 return;
683 }
684 boolean[] sep = new boolean[1];
685 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700686 csvScreenStats = parseStateList(DumpUtils.ADJ_SCREEN_NAMES_CSV,
687 ProcessStats.ADJ_SCREEN_MOD, args[i], sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700688 if (csvScreenStats == null) {
689 pw.println("Error in \"" + args[i] + "\": " + error[0]);
690 dumpHelp(pw);
691 return;
692 }
693 csvSepScreenStats = sep[0];
694 } else if ("--csv-mem".equals(arg)) {
695 i++;
696 if (i >= args.length) {
697 pw.println("Error: argument required for --csv-mem");
698 dumpHelp(pw);
699 return;
700 }
701 boolean[] sep = new boolean[1];
702 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700703 csvMemStats = parseStateList(DumpUtils.ADJ_MEM_NAMES_CSV, 1, args[i],
704 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700705 if (csvMemStats == null) {
706 pw.println("Error in \"" + args[i] + "\": " + error[0]);
707 dumpHelp(pw);
708 return;
709 }
710 csvSepMemStats = sep[0];
711 } else if ("--csv-proc".equals(arg)) {
712 i++;
713 if (i >= args.length) {
714 pw.println("Error: argument required for --csv-proc");
715 dumpHelp(pw);
716 return;
717 }
718 boolean[] sep = new boolean[1];
719 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700720 csvProcStats = parseStateList(DumpUtils.STATE_NAMES_CSV, 1, args[i],
721 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700722 if (csvProcStats == null) {
723 pw.println("Error in \"" + args[i] + "\": " + error[0]);
724 dumpHelp(pw);
725 return;
726 }
727 csvSepProcStats = sep[0];
728 } else if ("--details".equals(arg)) {
729 dumpDetails = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700730 } else if ("--full-details".equals(arg)) {
731 dumpFullDetails = true;
Dianne Hackborncb428552013-09-26 11:07:17 -0700732 } else if ("--hours".equals(arg)) {
733 i++;
734 if (i >= args.length) {
735 pw.println("Error: argument required for --hours");
736 dumpHelp(pw);
737 return;
738 }
739 try {
740 aggregateHours = Integer.parseInt(args[i]);
741 } catch (NumberFormatException e) {
742 pw.println("Error: --hours argument not an int -- " + args[i]);
743 dumpHelp(pw);
744 return;
745 }
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700746 } else if ("--last".equals(arg)) {
747 i++;
748 if (i >= args.length) {
749 pw.println("Error: argument required for --last");
750 dumpHelp(pw);
751 return;
752 }
753 try {
754 lastIndex = Integer.parseInt(args[i]);
755 } catch (NumberFormatException e) {
756 pw.println("Error: --last argument not an int -- " + args[i]);
757 dumpHelp(pw);
758 return;
759 }
Dianne Hackbornd052a942014-11-21 15:23:13 -0800760 } else if ("--max".equals(arg)) {
761 i++;
762 if (i >= args.length) {
763 pw.println("Error: argument required for --max");
764 dumpHelp(pw);
765 return;
766 }
767 try {
768 maxNum = Integer.parseInt(args[i]);
769 } catch (NumberFormatException e) {
770 pw.println("Error: --max argument not an int -- " + args[i]);
771 dumpHelp(pw);
772 return;
773 }
Dianne Hackborn164371f2013-10-01 19:10:13 -0700774 } else if ("--active".equals(arg)) {
775 activeOnly = true;
776 currentOnly = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700777 } else if ("--current".equals(arg)) {
778 currentOnly = true;
779 } else if ("--commit".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700780 synchronized (mAm) {
781 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
782 writeStateLocked(true, true);
783 pw.println("Process stats committed.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800784 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700785 }
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700786 } else if ("--reset".equals(arg)) {
787 synchronized (mAm) {
788 mProcessStats.resetSafely();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800789 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700790 pw.println("Process stats reset.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800791 quit = true;
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700792 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700793 } else if ("--clear".equals(arg)) {
794 synchronized (mAm) {
795 mProcessStats.resetSafely();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800796 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700797 ArrayList<String> files = getCommittedFiles(0, true, true);
798 if (files != null) {
799 for (int fi=0; fi<files.size(); fi++) {
800 (new File(files.get(fi))).delete();
801 }
802 }
803 pw.println("All process stats cleared.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800804 quit = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700805 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700806 } else if ("--write".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700807 synchronized (mAm) {
808 writeStateSyncLocked();
809 pw.println("Process stats written.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800810 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700811 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700812 } else if ("--read".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700813 synchronized (mAm) {
814 readLocked(mProcessStats, mFile);
815 pw.println("Process stats read.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800816 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700817 }
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800818 } else if ("--start-testing".equals(arg)) {
819 synchronized (mAm) {
820 mAm.setTestPssMode(true);
821 pw.println("Started high frequency sampling.");
822 quit = true;
823 }
824 } else if ("--stop-testing".equals(arg)) {
825 synchronized (mAm) {
826 mAm.setTestPssMode(false);
827 pw.println("Stopped high frequency sampling.");
828 quit = true;
829 }
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800830 } else if ("--pretend-screen-on".equals(arg)) {
831 synchronized (mAm) {
832 mInjectedScreenState = true;
833 }
834 quit = true;
835 } else if ("--pretend-screen-off".equals(arg)) {
836 synchronized (mAm) {
837 mInjectedScreenState = false;
838 }
839 quit = true;
840 } else if ("--stop-pretend-screen".equals(arg)) {
841 synchronized (mAm) {
842 mInjectedScreenState = null;
843 }
844 quit = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700845 } else if ("-h".equals(arg)) {
846 dumpHelp(pw);
847 return;
848 } else if ("-a".equals(arg)) {
849 dumpDetails = true;
850 dumpAll = true;
851 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
852 pw.println("Unknown option: " + arg);
853 dumpHelp(pw);
854 return;
855 } else {
856 // Not an option, last argument must be a package name.
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800857 reqPackage = arg;
858 // Include all details, since we know we are only going to
859 // be dumping a smaller set of data. In fact only the details
Dianne Hackbornab4a81b2014-10-09 17:59:38 -0700860 // contain per-package data, so this is needed to be able
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800861 // to dump anything at all when filtering by package.
862 dumpDetails = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700863 }
864 }
865 }
866
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800867 if (quit) {
868 return;
869 }
870
Dianne Hackbornd2932242013-08-05 18:18:42 -0700871 if (isCsv) {
872 pw.print("Processes running summed over");
873 if (!csvSepScreenStats) {
874 for (int i=0; i<csvScreenStats.length; i++) {
875 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700876 DumpUtils.printScreenLabelCsv(pw, csvScreenStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700877 }
878 }
879 if (!csvSepMemStats) {
880 for (int i=0; i<csvMemStats.length; i++) {
881 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700882 DumpUtils.printMemLabelCsv(pw, csvMemStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700883 }
884 }
885 if (!csvSepProcStats) {
886 for (int i=0; i<csvProcStats.length; i++) {
887 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700888 pw.print(DumpUtils.STATE_NAMES_CSV[csvProcStats[i]]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700889 }
890 }
891 pw.println();
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700892 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700893 dumpFilteredProcessesCsvLocked(pw, null,
894 csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
895 csvSepProcStats, csvProcStats, now, reqPackage);
896 /*
897 dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
898 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
899 true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
900 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
901 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
902 STATE_PREVIOUS, STATE_CACHED},
903 now, reqPackage);
904 dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
905 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
906 false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
907 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
908 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
909 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
910 STATE_PREVIOUS, STATE_CACHED},
911 now, reqPackage);
912 */
913 }
914 return;
Dianne Hackborncb428552013-09-26 11:07:17 -0700915 } else if (aggregateHours != 0) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800916 pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700917 dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
918 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700919 return;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700920 } else if (lastIndex > 0) {
921 pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":");
922 ArrayList<String> files = getCommittedFiles(0, false, true);
923 if (lastIndex >= files.size()) {
924 pw.print("Only have "); pw.print(files.size()); pw.println(" data sets");
925 return;
926 }
927 AtomicFile file = new AtomicFile(new File(files.get(lastIndex)));
928 ProcessStats processStats = new ProcessStats(false);
929 readLocked(processStats, file);
930 if (processStats.mReadError != null) {
931 if (isCheckin || isCompact) pw.print("err,");
932 pw.print("Failure reading "); pw.print(files.get(lastIndex));
933 pw.print("; "); pw.println(processStats.mReadError);
934 return;
935 }
936 String fileStr = file.getBaseFile().getPath();
937 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
938 if (isCheckin || isCompact) {
939 // Don't really need to lock because we uniquely own this object.
940 processStats.dumpCheckinLocked(pw, reqPackage);
941 } else {
942 pw.print("COMMITTED STATS FROM ");
943 pw.print(processStats.mTimePeriodStartClockStr);
944 if (checkedIn) pw.print(" (checked in)");
945 pw.println(":");
946 if (dumpDetails || dumpFullDetails) {
947 processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
948 activeOnly);
949 if (dumpAll) {
950 pw.print(" mFile="); pw.println(mFile.getBaseFile());
951 }
952 } else {
953 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
954 }
955 }
956 return;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700957 }
958
959 boolean sepNeeded = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800960 if (dumpAll || isCheckin) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700961 mWriteLock.lock();
962 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700963 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700964 if (files != null) {
Dianne Hackbornd052a942014-11-21 15:23:13 -0800965 int start = isCheckin ? 0 : (files.size() - maxNum);
966 if (start < 0) {
967 start = 0;
968 }
969 for (int i=start; i<files.size(); i++) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700970 if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
971 try {
972 AtomicFile file = new AtomicFile(new File(files.get(i)));
973 ProcessStats processStats = new ProcessStats(false);
974 readLocked(processStats, file);
975 if (processStats.mReadError != null) {
976 if (isCheckin || isCompact) pw.print("err,");
977 pw.print("Failure reading "); pw.print(files.get(i));
978 pw.print("; "); pw.println(processStats.mReadError);
979 if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
980 (new File(files.get(i))).delete();
981 continue;
982 }
983 String fileStr = file.getBaseFile().getPath();
984 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
985 if (isCheckin || isCompact) {
986 // Don't really need to lock because we uniquely own this object.
987 processStats.dumpCheckinLocked(pw, reqPackage);
988 } else {
989 if (sepNeeded) {
990 pw.println();
991 } else {
992 sepNeeded = true;
993 }
994 pw.print("COMMITTED STATS FROM ");
995 pw.print(processStats.mTimePeriodStartClockStr);
996 if (checkedIn) pw.print(" (checked in)");
997 pw.println(":");
998 // Don't really need to lock because we uniquely own this object.
Dianne Hackbornae36b232013-09-03 18:12:53 -0700999 // Always dump summary here, dumping all details is just too
1000 // much crud.
Dianne Hackborn53459a72013-09-17 17:14:57 -07001001 if (dumpFullDetails) {
Dianne Hackbornf7097a52014-05-13 09:56:14 -07001002 processStats.dumpLocked(pw, reqPackage, now, false, false,
Dianne Hackborn164371f2013-10-01 19:10:13 -07001003 activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001004 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001005 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001006 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001007 }
1008 if (isCheckin) {
1009 // Rename file suffix to mark that it has checked in.
1010 file.getBaseFile().renameTo(new File(
1011 fileStr + STATE_FILE_CHECKIN_SUFFIX));
1012 }
1013 } catch (Throwable e) {
1014 pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
1015 e.printStackTrace(pw);
1016 }
1017 }
1018 }
1019 } finally {
1020 mWriteLock.unlock();
1021 }
1022 }
1023 if (!isCheckin) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001024 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001025 if (isCompact) {
1026 mProcessStats.dumpCheckinLocked(pw, reqPackage);
1027 } else {
1028 if (sepNeeded) {
1029 pw.println();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001030 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001031 pw.println("CURRENT STATS:");
Dianne Hackborn53459a72013-09-17 17:14:57 -07001032 if (dumpDetails || dumpFullDetails) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001033 mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
1034 activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001035 if (dumpAll) {
1036 pw.print(" mFile="); pw.println(mFile.getBaseFile());
1037 }
1038 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001039 mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001040 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001041 sepNeeded = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001042 }
1043 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001044 if (!currentOnly) {
1045 if (sepNeeded) {
1046 pw.println();
1047 }
1048 pw.println("AGGREGATED OVER LAST 24 HOURS:");
1049 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
1050 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1051 pw.println();
1052 pw.println("AGGREGATED OVER LAST 3 HOURS:");
1053 dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
1054 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1055 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001056 }
1057 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001058
Yi Jin676d1ac2018-01-25 15:40:28 -08001059 private void dumpAggregatedStats(ProtoOutputStream proto, long fieldId, int aggregateHours, long now) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001060 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
1061 - (ProcessStats.COMMIT_PERIOD/2));
1062 if (pfd == null) {
1063 return;
1064 }
1065 ProcessStats stats = new ProcessStats(false);
1066 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1067 stats.read(stream);
1068 if (stats.mReadError != null) {
1069 return;
1070 }
Yi Jin676d1ac2018-01-25 15:40:28 -08001071 stats.writeToProto(proto, fieldId, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001072 }
1073
1074 private void dumpProto(FileDescriptor fd) {
1075 final ProtoOutputStream proto = new ProtoOutputStream(fd);
1076
1077 // dump current procstats
Yi Jin9680cfa2017-09-15 15:14:43 -07001078 long now;
1079 synchronized (mAm) {
1080 now = SystemClock.uptimeMillis();
Yi Jin676d1ac2018-01-25 15:40:28 -08001081 mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001082 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001083
1084 // aggregated over last 3 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001085 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_3HRS, 3, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001086
1087 // aggregated over last 24 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001088 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_24HRS, 24, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001089
1090 proto.flush();
1091 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001092}