blob: 8bf320e0c387933f6a8563304a5804ef6ce3d461 [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
138 public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
139 mMemFactorLowered = memFactor < mLastMemOnlyState;
140 mLastMemOnlyState = memFactor;
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800141 if (mInjectedScreenState != null) {
142 screenOn = mInjectedScreenState;
143 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700144 if (screenOn) {
145 memFactor += ProcessStats.ADJ_SCREEN_ON;
146 }
147 if (memFactor != mProcessStats.mMemFactor) {
148 if (mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING) {
149 mProcessStats.mMemFactorDurations[mProcessStats.mMemFactor]
150 += now - mProcessStats.mStartTime;
151 }
152 mProcessStats.mMemFactor = memFactor;
153 mProcessStats.mStartTime = now;
Dianne Hackborn3accca02013-09-20 09:32:11 -0700154 final ArrayMap<String, SparseArray<LongSparseArray<ProcessStats.PackageState>>> pmap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700155 = mProcessStats.mPackages.getMap();
Dianne Hackborn8472e612014-01-23 17:57:20 -0800156 for (int ipkg=pmap.size()-1; ipkg>=0; ipkg--) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700157 final SparseArray<LongSparseArray<ProcessStats.PackageState>> uids =
158 pmap.valueAt(ipkg);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800159 for (int iuid=uids.size()-1; iuid>=0; iuid--) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700160 final LongSparseArray<ProcessStats.PackageState> vers = uids.valueAt(iuid);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800161 for (int iver=vers.size()-1; iver>=0; iver--) {
162 final ProcessStats.PackageState pkg = vers.valueAt(iver);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700163 final ArrayMap<String, ServiceState> services = pkg.mServices;
Dianne Hackborn8472e612014-01-23 17:57:20 -0800164 for (int isvc=services.size()-1; isvc>=0; isvc--) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700165 final ServiceState service = services.valueAt(isvc);
166 service.setMemFactor(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700167 }
168 }
169 }
170 }
171 return true;
172 }
173 return false;
174 }
175
176 public int getMemFactorLocked() {
177 return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0;
178 }
179
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700180 public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem,
181 long nativeMem) {
182 mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem);
183 }
184
Dianne Hackbornd2932242013-08-05 18:18:42 -0700185 public boolean shouldWriteNowLocked(long now) {
186 if (now > (mLastWriteTime+WRITE_PERIOD)) {
187 if (SystemClock.elapsedRealtime()
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700188 > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD) &&
189 SystemClock.uptimeMillis()
190 > (mProcessStats.mTimePeriodStartUptime+ProcessStats.COMMIT_UPTIME_PERIOD)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700191 mCommitPending = true;
192 }
193 return true;
194 }
195 return false;
196 }
197
198 public void shutdownLocked() {
199 Slog.w(TAG, "Writing process stats before shutdown...");
200 mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN;
201 writeStateSyncLocked();
202 mShuttingDown = true;
203 }
204
205 public void writeStateAsyncLocked() {
206 writeStateLocked(false);
207 }
208
209 public void writeStateSyncLocked() {
210 writeStateLocked(true);
211 }
212
213 private void writeStateLocked(boolean sync) {
214 if (mShuttingDown) {
215 return;
216 }
217 boolean commitPending = mCommitPending;
218 mCommitPending = false;
219 writeStateLocked(sync, commitPending);
220 }
221
222 public void writeStateLocked(boolean sync, final boolean commit) {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800223 final long totalTime;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700224 synchronized (mPendingWriteLock) {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800225 final long now = SystemClock.uptimeMillis();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700226 if (mPendingWrite == null || !mPendingWriteCommitted) {
227 mPendingWrite = Parcel.obtain();
228 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700229 mProcessStats.mTimePeriodEndUptime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700230 if (commit) {
231 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
232 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700233 mProcessStats.writeToParcel(mPendingWrite, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700234 mPendingWriteFile = new AtomicFile(mFile.getBaseFile());
235 mPendingWriteCommitted = commit;
236 }
237 if (commit) {
238 mProcessStats.resetSafely();
239 updateFile();
240 }
241 mLastWriteTime = SystemClock.uptimeMillis();
Dianne Hackborne17b4452018-01-10 13:15:40 -0800242 totalTime = SystemClock.uptimeMillis() - now;
243 if (DEBUG) Slog.d(TAG, "Prepared write state in " + now + "ms");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700244 if (!sync) {
245 BackgroundThread.getHandler().post(new Runnable() {
246 @Override public void run() {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800247 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700248 }
249 });
250 return;
251 }
252 }
253
Dianne Hackborne17b4452018-01-10 13:15:40 -0800254 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700255 }
256
257 private void updateFile() {
258 mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX
259 + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
260 mLastWriteTime = SystemClock.uptimeMillis();
261 }
262
Dianne Hackborne17b4452018-01-10 13:15:40 -0800263 void performWriteState(long initialTime) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700264 if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
265 Parcel data;
266 AtomicFile file;
267 synchronized (mPendingWriteLock) {
268 data = mPendingWrite;
269 file = mPendingWriteFile;
270 mPendingWriteCommitted = false;
271 if (data == null) {
272 return;
273 }
274 mPendingWrite = null;
275 mPendingWriteFile = null;
276 mWriteLock.lock();
277 }
278
Dianne Hackborne17b4452018-01-10 13:15:40 -0800279 final long startTime = SystemClock.uptimeMillis();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700280 FileOutputStream stream = null;
281 try {
282 stream = file.startWrite();
283 stream.write(data.marshall());
284 stream.flush();
285 file.finishWrite(stream);
Dianne Hackborne17b4452018-01-10 13:15:40 -0800286 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
287 "procstats", SystemClock.uptimeMillis() - startTime + initialTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700288 if (DEBUG) Slog.d(TAG, "Write completed successfully!");
289 } catch (IOException e) {
290 Slog.w(TAG, "Error writing process statistics", e);
291 file.failWrite(stream);
292 } finally {
293 data.recycle();
294 trimHistoricStatesWriteLocked();
295 mWriteLock.unlock();
296 }
297 }
298
Dianne Hackbornd2932242013-08-05 18:18:42 -0700299 boolean readLocked(ProcessStats stats, AtomicFile file) {
300 try {
301 FileInputStream stream = file.openRead();
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700302 stats.read(stream);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700303 stream.close();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700304 if (stats.mReadError != null) {
305 Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
306 if (DEBUG) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700307 ArrayMap<String, SparseArray<ProcessState>> procMap = stats.mProcesses.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700308 final int NPROC = procMap.size();
309 for (int ip=0; ip<NPROC; ip++) {
310 Slog.w(TAG, "Process: " + procMap.keyAt(ip));
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700311 SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700312 final int NUID = uids.size();
313 for (int iu=0; iu<NUID; iu++) {
314 Slog.w(TAG, " Uid " + uids.keyAt(iu) + ": " + uids.valueAt(iu));
315 }
316 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700317 ArrayMap<String, SparseArray<LongSparseArray<ProcessStats.PackageState>>> pkgMap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700318 = stats.mPackages.getMap();
319 final int NPKG = pkgMap.size();
320 for (int ip=0; ip<NPKG; ip++) {
321 Slog.w(TAG, "Package: " + pkgMap.keyAt(ip));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700322 SparseArray<LongSparseArray<ProcessStats.PackageState>> uids
Dianne Hackborn8472e612014-01-23 17:57:20 -0800323 = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700324 final int NUID = uids.size();
325 for (int iu=0; iu<NUID; iu++) {
326 Slog.w(TAG, " Uid: " + uids.keyAt(iu));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700327 LongSparseArray<ProcessStats.PackageState> vers = uids.valueAt(iu);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800328 final int NVERS = vers.size();
329 for (int iv=0; iv<NVERS; iv++) {
330 Slog.w(TAG, " Vers: " + vers.keyAt(iv));
331 ProcessStats.PackageState pkgState = vers.valueAt(iv);
332 final int NPROCS = pkgState.mProcesses.size();
333 for (int iproc=0; iproc<NPROCS; iproc++) {
334 Slog.w(TAG, " Process " + pkgState.mProcesses.keyAt(iproc)
335 + ": " + pkgState.mProcesses.valueAt(iproc));
336 }
337 final int NSRVS = pkgState.mServices.size();
338 for (int isvc=0; isvc<NSRVS; isvc++) {
339 Slog.w(TAG, " Service " + pkgState.mServices.keyAt(isvc)
340 + ": " + pkgState.mServices.valueAt(isvc));
341
342 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700343 }
344 }
345 }
346 }
347 return false;
348 }
349 } catch (Throwable e) {
350 stats.mReadError = "caught exception: " + e;
351 Slog.e(TAG, "Error reading process statistics", e);
352 return false;
353 }
354 return true;
355 }
356
Dianne Hackborn53459a72013-09-17 17:14:57 -0700357 private ArrayList<String> getCommittedFiles(int minNum, boolean inclCurrent,
358 boolean inclCheckedIn) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700359 File[] files = mBaseDir.listFiles();
360 if (files == null || files.length <= minNum) {
361 return null;
362 }
363 ArrayList<String> filesArray = new ArrayList<String>(files.length);
364 String currentFile = mFile.getBaseFile().getPath();
365 if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
366 for (int i=0; i<files.length; i++) {
367 File file = files[i];
368 String fileStr = file.getPath();
369 if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700370 if (!inclCheckedIn && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700371 if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
372 continue;
373 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700374 if (!inclCurrent && fileStr.equals(currentFile)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700375 if (DEBUG) Slog.d(TAG, "Skipping: current stats");
376 continue;
377 }
378 filesArray.add(fileStr);
379 }
380 Collections.sort(filesArray);
381 return filesArray;
382 }
383
384 public void trimHistoricStatesWriteLocked() {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700385 ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700386 if (filesArray == null) {
387 return;
388 }
389 while (filesArray.size() > MAX_HISTORIC_STATES) {
390 String file = filesArray.remove(0);
391 Slog.i(TAG, "Pruning old procstats: " + file);
392 (new File(file)).delete();
393 }
394 }
395
396 boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
397 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
398 boolean sepProcStates, int[] procStates, long now, String reqPackage) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700399 ArrayList<ProcessState> procs = mProcessStats.collectProcessesLocked(
Dianne Hackborn164371f2013-10-01 19:10:13 -0700400 screenStates, memStates, procStates, procStates, now, reqPackage, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700401 if (procs.size() > 0) {
402 if (header != null) {
403 pw.println(header);
404 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700405 DumpUtils.dumpProcessListCsv(pw, procs, sepScreenStates, screenStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700406 sepMemStates, memStates, sepProcStates, procStates, now);
407 return true;
408 }
409 return false;
410 }
411
412 static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
413 String[] outError) {
414 ArrayList<Integer> res = new ArrayList<Integer>();
415 int lastPos = 0;
416 for (int i=0; i<=arg.length(); i++) {
417 char c = i < arg.length() ? arg.charAt(i) : 0;
418 if (c != ',' && c != '+' && c != ' ' && c != 0) {
419 continue;
420 }
421 boolean isSep = c == ',';
422 if (lastPos == 0) {
423 // We now know the type of op.
424 outSep[0] = isSep;
425 } else if (c != 0 && outSep[0] != isSep) {
426 outError[0] = "inconsistent separators (can't mix ',' with '+')";
427 return null;
428 }
429 if (lastPos < (i-1)) {
430 String str = arg.substring(lastPos, i);
431 for (int j=0; j<states.length; j++) {
432 if (str.equals(states[j])) {
433 res.add(j);
434 str = null;
435 break;
436 }
437 }
438 if (str != null) {
439 outError[0] = "invalid word \"" + str + "\"";
440 return null;
441 }
442 }
443 lastPos = i + 1;
444 }
445
446 int[] finalRes = new int[res.size()];
447 for (int i=0; i<res.size(); i++) {
448 finalRes[i] = res.get(i) * mult;
449 }
450 return finalRes;
451 }
452
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700453 public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700454 mAm.mContext.enforceCallingOrSelfPermission(
455 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700456 Parcel current = Parcel.obtain();
riddle_hsu61231a52014-11-15 18:40:08 +0800457 synchronized (mAm) {
458 long now = SystemClock.uptimeMillis();
459 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
460 mProcessStats.mTimePeriodEndUptime = now;
461 mProcessStats.writeToParcel(current, now, 0);
462 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700463 mWriteLock.lock();
464 try {
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700465 if (historic != null) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700466 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700467 if (files != null) {
468 for (int i=files.size()-1; i>=0; i--) {
469 try {
470 ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
471 new File(files.get(i)), ParcelFileDescriptor.MODE_READ_ONLY);
472 historic.add(pfd);
473 } catch (IOException e) {
474 Slog.w(TAG, "Failure opening procstat file " + files.get(i), e);
475 }
476 }
477 }
478 }
479 } finally {
480 mWriteLock.unlock();
481 }
482 return current.marshall();
483 }
484
Dianne Hackborn53459a72013-09-17 17:14:57 -0700485 public ParcelFileDescriptor getStatsOverTime(long minTime) {
486 mAm.mContext.enforceCallingOrSelfPermission(
487 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
riddle_hsu61231a52014-11-15 18:40:08 +0800488 Parcel current = Parcel.obtain();
489 long curTime;
490 synchronized (mAm) {
491 long now = SystemClock.uptimeMillis();
492 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
493 mProcessStats.mTimePeriodEndUptime = now;
494 mProcessStats.writeToParcel(current, now, 0);
495 curTime = mProcessStats.mTimePeriodEndRealtime
496 - mProcessStats.mTimePeriodStartRealtime;
497 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700498 mWriteLock.lock();
499 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700500 if (curTime < minTime) {
501 // Need to add in older stats to reach desired time.
502 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborncb428552013-09-26 11:07:17 -0700503 if (files != null && files.size() > 0) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700504 current.setDataPosition(0);
505 ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current);
506 current.recycle();
Dianne Hackborn59da6792013-10-10 18:27:24 -0700507 int i = files.size()-1;
508 while (i >= 0 && (stats.mTimePeriodEndRealtime
Dianne Hackborn53459a72013-09-17 17:14:57 -0700509 - stats.mTimePeriodStartRealtime) < minTime) {
510 AtomicFile file = new AtomicFile(new File(files.get(i)));
Dianne Hackborn59da6792013-10-10 18:27:24 -0700511 i--;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700512 ProcessStats moreStats = new ProcessStats(false);
513 readLocked(moreStats, file);
514 if (moreStats.mReadError == null) {
515 stats.add(moreStats);
516 StringBuilder sb = new StringBuilder();
517 sb.append("Added stats: ");
518 sb.append(moreStats.mTimePeriodStartClockStr);
519 sb.append(", over ");
520 TimeUtils.formatDuration(moreStats.mTimePeriodEndRealtime
521 - moreStats.mTimePeriodStartRealtime, sb);
522 Slog.i(TAG, sb.toString());
523 } else {
Dianne Hackborn59da6792013-10-10 18:27:24 -0700524 Slog.w(TAG, "Failure reading " + files.get(i+1) + "; "
Dianne Hackborn53459a72013-09-17 17:14:57 -0700525 + moreStats.mReadError);
526 continue;
527 }
528 }
529 current = Parcel.obtain();
530 stats.writeToParcel(current, 0);
531 }
532 }
533 final byte[] outData = current.marshall();
534 current.recycle();
535 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
536 Thread thr = new Thread("ProcessStats pipe output") {
537 public void run() {
538 FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]);
539 try {
540 fout.write(outData);
541 fout.close();
542 } catch (IOException e) {
543 Slog.w(TAG, "Failure writing pipe", e);
544 }
545 }
546 };
547 thr.start();
548 return fds[0];
549 } catch (IOException e) {
550 Slog.w(TAG, "Failed building output pipe", e);
551 } finally {
552 mWriteLock.unlock();
553 }
554 return null;
555 }
556
Dianne Hackborn69cb00b2013-08-09 16:16:56 -0700557 public int getCurrentMemoryState() {
558 synchronized (mAm) {
559 return mLastMemOnlyState;
560 }
561 }
562
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700563 private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
564 String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
565 boolean dumpAll, boolean activeOnly) {
566 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
567 - (ProcessStats.COMMIT_PERIOD/2));
568 if (pfd == null) {
569 pw.println("Unable to build stats!");
570 return;
571 }
572 ProcessStats stats = new ProcessStats(false);
573 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
574 stats.read(stream);
575 if (stats.mReadError != null) {
576 pw.print("Failure reading: "); pw.println(stats.mReadError);
577 return;
578 }
579 if (isCompact) {
580 stats.dumpCheckinLocked(pw, reqPackage);
581 } else {
582 if (dumpDetails || dumpFullDetails) {
583 stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
584 } else {
585 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
586 }
587 }
588 }
589
Dianne Hackbornd2932242013-08-05 18:18:42 -0700590 static private void dumpHelp(PrintWriter pw) {
591 pw.println("Process stats (procstats) dump options:");
592 pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700593 pw.println(" [--details] [--full-details] [--current] [--hours N] [--last N]");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800594 pw.println(" [--max N] --active] [--commit] [--reset] [--clear] [--write] [-h]");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800595 pw.println(" [--start-testing] [--stop-testing] ");
596 pw.println(" [--pretend-screen-on] [--pretend-screen-off] [--stop-pretend-screen]");
597 pw.println(" [<package.name>]");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700598 pw.println(" --checkin: perform a checkin: print and delete old committed states.");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800599 pw.println(" -c: print only state in checkin format.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700600 pw.println(" --csv: output data suitable for putting in a spreadsheet.");
601 pw.println(" --csv-screen: on, off.");
602 pw.println(" --csv-mem: norm, mod, low, crit.");
603 pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
604 pw.println(" service, home, prev, cached");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700605 pw.println(" --details: dump per-package details, not just summary.");
606 pw.println(" --full-details: dump all timing and active state details.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700607 pw.println(" --current: only dump current state.");
Dianne Hackborncb428552013-09-26 11:07:17 -0700608 pw.println(" --hours: aggregate over about N last hours.");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700609 pw.println(" --last: only show the last committed stats at index N (starting at 1).");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800610 pw.println(" --max: for -a, max num of historical batches to print.");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700611 pw.println(" --active: only show currently active processes/services.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700612 pw.println(" --commit: commit current stats to disk and reset to start new stats.");
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700613 pw.println(" --reset: reset current stats, without committing.");
Dianne Hackborn53459a72013-09-17 17:14:57 -0700614 pw.println(" --clear: clear all stats; does both --reset and deletes old stats.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700615 pw.println(" --write: write current in-memory stats to disk.");
616 pw.println(" --read: replace current stats with last-written stats.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800617 pw.println(" --start-testing: clear all stats and starting high frequency pss sampling.");
618 pw.println(" --stop-testing: stop high frequency pss sampling.");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800619 pw.println(" --pretend-screen-on: pretend screen is on.");
620 pw.println(" --pretend-screen-off: pretend screen is off.");
621 pw.println(" --stop-pretend-screen: forget \"pretend screen\" and use the real state.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700622 pw.println(" -a: print everything.");
623 pw.println(" -h: print this help text.");
624 pw.println(" <package.name>: optional name of package to filter output by.");
625 }
626
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700627 @Override
628 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -0600629 if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600630 TAG, pw)) return;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700631
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700632 long ident = Binder.clearCallingIdentity();
633 try {
Yi Jin9680cfa2017-09-15 15:14:43 -0700634 if (args.length > 0 && "--proto".equals(args[0])) {
635 dumpProto(fd);
636 } else {
637 dumpInner(pw, args);
638 }
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700639 } finally {
640 Binder.restoreCallingIdentity(ident);
641 }
642 }
643
Yi Jin9680cfa2017-09-15 15:14:43 -0700644 private void dumpInner(PrintWriter pw, String[] args) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700645 final long now = SystemClock.uptimeMillis();
646
647 boolean isCheckin = false;
648 boolean isCompact = false;
649 boolean isCsv = false;
650 boolean currentOnly = false;
651 boolean dumpDetails = false;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700652 boolean dumpFullDetails = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700653 boolean dumpAll = false;
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800654 boolean quit = false;
Dianne Hackborncb428552013-09-26 11:07:17 -0700655 int aggregateHours = 0;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700656 int lastIndex = 0;
Dianne Hackbornd052a942014-11-21 15:23:13 -0800657 int maxNum = 2;
Dianne Hackborn164371f2013-10-01 19:10:13 -0700658 boolean activeOnly = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700659 String reqPackage = null;
660 boolean csvSepScreenStats = false;
661 int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
662 boolean csvSepMemStats = false;
663 int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL};
664 boolean csvSepProcStats = true;
665 int[] csvProcStats = ProcessStats.ALL_PROC_STATES;
666 if (args != null) {
667 for (int i=0; i<args.length; i++) {
668 String arg = args[i];
669 if ("--checkin".equals(arg)) {
670 isCheckin = true;
671 } else if ("-c".equals(arg)) {
672 isCompact = true;
673 } else if ("--csv".equals(arg)) {
674 isCsv = true;
675 } else if ("--csv-screen".equals(arg)) {
676 i++;
677 if (i >= args.length) {
678 pw.println("Error: argument required for --csv-screen");
679 dumpHelp(pw);
680 return;
681 }
682 boolean[] sep = new boolean[1];
683 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700684 csvScreenStats = parseStateList(DumpUtils.ADJ_SCREEN_NAMES_CSV,
685 ProcessStats.ADJ_SCREEN_MOD, args[i], sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700686 if (csvScreenStats == null) {
687 pw.println("Error in \"" + args[i] + "\": " + error[0]);
688 dumpHelp(pw);
689 return;
690 }
691 csvSepScreenStats = sep[0];
692 } else if ("--csv-mem".equals(arg)) {
693 i++;
694 if (i >= args.length) {
695 pw.println("Error: argument required for --csv-mem");
696 dumpHelp(pw);
697 return;
698 }
699 boolean[] sep = new boolean[1];
700 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700701 csvMemStats = parseStateList(DumpUtils.ADJ_MEM_NAMES_CSV, 1, args[i],
702 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700703 if (csvMemStats == null) {
704 pw.println("Error in \"" + args[i] + "\": " + error[0]);
705 dumpHelp(pw);
706 return;
707 }
708 csvSepMemStats = sep[0];
709 } else if ("--csv-proc".equals(arg)) {
710 i++;
711 if (i >= args.length) {
712 pw.println("Error: argument required for --csv-proc");
713 dumpHelp(pw);
714 return;
715 }
716 boolean[] sep = new boolean[1];
717 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700718 csvProcStats = parseStateList(DumpUtils.STATE_NAMES_CSV, 1, args[i],
719 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700720 if (csvProcStats == null) {
721 pw.println("Error in \"" + args[i] + "\": " + error[0]);
722 dumpHelp(pw);
723 return;
724 }
725 csvSepProcStats = sep[0];
726 } else if ("--details".equals(arg)) {
727 dumpDetails = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700728 } else if ("--full-details".equals(arg)) {
729 dumpFullDetails = true;
Dianne Hackborncb428552013-09-26 11:07:17 -0700730 } else if ("--hours".equals(arg)) {
731 i++;
732 if (i >= args.length) {
733 pw.println("Error: argument required for --hours");
734 dumpHelp(pw);
735 return;
736 }
737 try {
738 aggregateHours = Integer.parseInt(args[i]);
739 } catch (NumberFormatException e) {
740 pw.println("Error: --hours argument not an int -- " + args[i]);
741 dumpHelp(pw);
742 return;
743 }
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700744 } else if ("--last".equals(arg)) {
745 i++;
746 if (i >= args.length) {
747 pw.println("Error: argument required for --last");
748 dumpHelp(pw);
749 return;
750 }
751 try {
752 lastIndex = Integer.parseInt(args[i]);
753 } catch (NumberFormatException e) {
754 pw.println("Error: --last argument not an int -- " + args[i]);
755 dumpHelp(pw);
756 return;
757 }
Dianne Hackbornd052a942014-11-21 15:23:13 -0800758 } else if ("--max".equals(arg)) {
759 i++;
760 if (i >= args.length) {
761 pw.println("Error: argument required for --max");
762 dumpHelp(pw);
763 return;
764 }
765 try {
766 maxNum = Integer.parseInt(args[i]);
767 } catch (NumberFormatException e) {
768 pw.println("Error: --max argument not an int -- " + args[i]);
769 dumpHelp(pw);
770 return;
771 }
Dianne Hackborn164371f2013-10-01 19:10:13 -0700772 } else if ("--active".equals(arg)) {
773 activeOnly = true;
774 currentOnly = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700775 } else if ("--current".equals(arg)) {
776 currentOnly = true;
777 } else if ("--commit".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700778 synchronized (mAm) {
779 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
780 writeStateLocked(true, true);
781 pw.println("Process stats committed.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800782 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700783 }
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700784 } else if ("--reset".equals(arg)) {
785 synchronized (mAm) {
786 mProcessStats.resetSafely();
787 pw.println("Process stats reset.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800788 quit = true;
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700789 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700790 } else if ("--clear".equals(arg)) {
791 synchronized (mAm) {
792 mProcessStats.resetSafely();
793 ArrayList<String> files = getCommittedFiles(0, true, true);
794 if (files != null) {
795 for (int fi=0; fi<files.size(); fi++) {
796 (new File(files.get(fi))).delete();
797 }
798 }
799 pw.println("All process stats cleared.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800800 quit = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700801 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700802 } else if ("--write".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700803 synchronized (mAm) {
804 writeStateSyncLocked();
805 pw.println("Process stats written.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800806 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700807 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700808 } else if ("--read".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700809 synchronized (mAm) {
810 readLocked(mProcessStats, mFile);
811 pw.println("Process stats read.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800812 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700813 }
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800814 } else if ("--start-testing".equals(arg)) {
815 synchronized (mAm) {
816 mAm.setTestPssMode(true);
817 pw.println("Started high frequency sampling.");
818 quit = true;
819 }
820 } else if ("--stop-testing".equals(arg)) {
821 synchronized (mAm) {
822 mAm.setTestPssMode(false);
823 pw.println("Stopped high frequency sampling.");
824 quit = true;
825 }
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800826 } else if ("--pretend-screen-on".equals(arg)) {
827 synchronized (mAm) {
828 mInjectedScreenState = true;
829 }
830 quit = true;
831 } else if ("--pretend-screen-off".equals(arg)) {
832 synchronized (mAm) {
833 mInjectedScreenState = false;
834 }
835 quit = true;
836 } else if ("--stop-pretend-screen".equals(arg)) {
837 synchronized (mAm) {
838 mInjectedScreenState = null;
839 }
840 quit = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700841 } else if ("-h".equals(arg)) {
842 dumpHelp(pw);
843 return;
844 } else if ("-a".equals(arg)) {
845 dumpDetails = true;
846 dumpAll = true;
847 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
848 pw.println("Unknown option: " + arg);
849 dumpHelp(pw);
850 return;
851 } else {
852 // Not an option, last argument must be a package name.
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800853 reqPackage = arg;
854 // Include all details, since we know we are only going to
855 // be dumping a smaller set of data. In fact only the details
Dianne Hackbornab4a81b2014-10-09 17:59:38 -0700856 // contain per-package data, so this is needed to be able
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800857 // to dump anything at all when filtering by package.
858 dumpDetails = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700859 }
860 }
861 }
862
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800863 if (quit) {
864 return;
865 }
866
Dianne Hackbornd2932242013-08-05 18:18:42 -0700867 if (isCsv) {
868 pw.print("Processes running summed over");
869 if (!csvSepScreenStats) {
870 for (int i=0; i<csvScreenStats.length; i++) {
871 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700872 DumpUtils.printScreenLabelCsv(pw, csvScreenStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700873 }
874 }
875 if (!csvSepMemStats) {
876 for (int i=0; i<csvMemStats.length; i++) {
877 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700878 DumpUtils.printMemLabelCsv(pw, csvMemStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700879 }
880 }
881 if (!csvSepProcStats) {
882 for (int i=0; i<csvProcStats.length; i++) {
883 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700884 pw.print(DumpUtils.STATE_NAMES_CSV[csvProcStats[i]]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700885 }
886 }
887 pw.println();
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700888 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700889 dumpFilteredProcessesCsvLocked(pw, null,
890 csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
891 csvSepProcStats, csvProcStats, now, reqPackage);
892 /*
893 dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
894 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
895 true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
896 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
897 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
898 STATE_PREVIOUS, STATE_CACHED},
899 now, reqPackage);
900 dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
901 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
902 false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
903 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
904 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
905 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
906 STATE_PREVIOUS, STATE_CACHED},
907 now, reqPackage);
908 */
909 }
910 return;
Dianne Hackborncb428552013-09-26 11:07:17 -0700911 } else if (aggregateHours != 0) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800912 pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700913 dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
914 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700915 return;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700916 } else if (lastIndex > 0) {
917 pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":");
918 ArrayList<String> files = getCommittedFiles(0, false, true);
919 if (lastIndex >= files.size()) {
920 pw.print("Only have "); pw.print(files.size()); pw.println(" data sets");
921 return;
922 }
923 AtomicFile file = new AtomicFile(new File(files.get(lastIndex)));
924 ProcessStats processStats = new ProcessStats(false);
925 readLocked(processStats, file);
926 if (processStats.mReadError != null) {
927 if (isCheckin || isCompact) pw.print("err,");
928 pw.print("Failure reading "); pw.print(files.get(lastIndex));
929 pw.print("; "); pw.println(processStats.mReadError);
930 return;
931 }
932 String fileStr = file.getBaseFile().getPath();
933 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
934 if (isCheckin || isCompact) {
935 // Don't really need to lock because we uniquely own this object.
936 processStats.dumpCheckinLocked(pw, reqPackage);
937 } else {
938 pw.print("COMMITTED STATS FROM ");
939 pw.print(processStats.mTimePeriodStartClockStr);
940 if (checkedIn) pw.print(" (checked in)");
941 pw.println(":");
942 if (dumpDetails || dumpFullDetails) {
943 processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
944 activeOnly);
945 if (dumpAll) {
946 pw.print(" mFile="); pw.println(mFile.getBaseFile());
947 }
948 } else {
949 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
950 }
951 }
952 return;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700953 }
954
955 boolean sepNeeded = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800956 if (dumpAll || isCheckin) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700957 mWriteLock.lock();
958 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700959 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700960 if (files != null) {
Dianne Hackbornd052a942014-11-21 15:23:13 -0800961 int start = isCheckin ? 0 : (files.size() - maxNum);
962 if (start < 0) {
963 start = 0;
964 }
965 for (int i=start; i<files.size(); i++) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700966 if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
967 try {
968 AtomicFile file = new AtomicFile(new File(files.get(i)));
969 ProcessStats processStats = new ProcessStats(false);
970 readLocked(processStats, file);
971 if (processStats.mReadError != null) {
972 if (isCheckin || isCompact) pw.print("err,");
973 pw.print("Failure reading "); pw.print(files.get(i));
974 pw.print("; "); pw.println(processStats.mReadError);
975 if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
976 (new File(files.get(i))).delete();
977 continue;
978 }
979 String fileStr = file.getBaseFile().getPath();
980 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
981 if (isCheckin || isCompact) {
982 // Don't really need to lock because we uniquely own this object.
983 processStats.dumpCheckinLocked(pw, reqPackage);
984 } else {
985 if (sepNeeded) {
986 pw.println();
987 } else {
988 sepNeeded = true;
989 }
990 pw.print("COMMITTED STATS FROM ");
991 pw.print(processStats.mTimePeriodStartClockStr);
992 if (checkedIn) pw.print(" (checked in)");
993 pw.println(":");
994 // Don't really need to lock because we uniquely own this object.
Dianne Hackbornae36b232013-09-03 18:12:53 -0700995 // Always dump summary here, dumping all details is just too
996 // much crud.
Dianne Hackborn53459a72013-09-17 17:14:57 -0700997 if (dumpFullDetails) {
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700998 processStats.dumpLocked(pw, reqPackage, now, false, false,
Dianne Hackborn164371f2013-10-01 19:10:13 -0700999 activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001000 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001001 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001002 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001003 }
1004 if (isCheckin) {
1005 // Rename file suffix to mark that it has checked in.
1006 file.getBaseFile().renameTo(new File(
1007 fileStr + STATE_FILE_CHECKIN_SUFFIX));
1008 }
1009 } catch (Throwable e) {
1010 pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
1011 e.printStackTrace(pw);
1012 }
1013 }
1014 }
1015 } finally {
1016 mWriteLock.unlock();
1017 }
1018 }
1019 if (!isCheckin) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001020 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001021 if (isCompact) {
1022 mProcessStats.dumpCheckinLocked(pw, reqPackage);
1023 } else {
1024 if (sepNeeded) {
1025 pw.println();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001026 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001027 pw.println("CURRENT STATS:");
Dianne Hackborn53459a72013-09-17 17:14:57 -07001028 if (dumpDetails || dumpFullDetails) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001029 mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
1030 activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001031 if (dumpAll) {
1032 pw.print(" mFile="); pw.println(mFile.getBaseFile());
1033 }
1034 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001035 mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001036 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001037 sepNeeded = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001038 }
1039 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001040 if (!currentOnly) {
1041 if (sepNeeded) {
1042 pw.println();
1043 }
1044 pw.println("AGGREGATED OVER LAST 24 HOURS:");
1045 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
1046 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1047 pw.println();
1048 pw.println("AGGREGATED OVER LAST 3 HOURS:");
1049 dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
1050 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1051 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001052 }
1053 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001054
Yi Jin676d1ac2018-01-25 15:40:28 -08001055 private void dumpAggregatedStats(ProtoOutputStream proto, long fieldId, int aggregateHours, long now) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001056 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
1057 - (ProcessStats.COMMIT_PERIOD/2));
1058 if (pfd == null) {
1059 return;
1060 }
1061 ProcessStats stats = new ProcessStats(false);
1062 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1063 stats.read(stream);
1064 if (stats.mReadError != null) {
1065 return;
1066 }
Yi Jin676d1ac2018-01-25 15:40:28 -08001067 stats.writeToProto(proto, fieldId, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001068 }
1069
1070 private void dumpProto(FileDescriptor fd) {
1071 final ProtoOutputStream proto = new ProtoOutputStream(fd);
1072
1073 // dump current procstats
Yi Jin9680cfa2017-09-15 15:14:43 -07001074 long now;
1075 synchronized (mAm) {
1076 now = SystemClock.uptimeMillis();
Yi Jin676d1ac2018-01-25 15:40:28 -08001077 mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001078 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001079
1080 // aggregated over last 3 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001081 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_3HRS, 3, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001082
1083 // aggregated over last 24 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001084 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_24HRS, 24, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001085
1086 proto.flush();
1087 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001088}