blob: 39aed7cf3d67fc8d0b42d38689fe855408d5f465 [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;
Dianne Hackbornd2932242013-08-05 18:18:42 -070026import android.util.ArrayMap;
27import android.util.AtomicFile;
28import android.util.Slog;
29import android.util.SparseArray;
Dianne Hackborn53459a72013-09-17 17:14:57 -070030import android.util.TimeUtils;
Makoto Onuki3ed5be32017-02-01 14:04:47 -080031
32import com.android.internal.annotations.GuardedBy;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070033import com.android.internal.app.procstats.DumpUtils;
34import com.android.internal.app.procstats.IProcessStats;
35import com.android.internal.app.procstats.ProcessState;
36import com.android.internal.app.procstats.ProcessStats;
37import com.android.internal.app.procstats.ServiceState;
Dianne Hackbornd2932242013-08-05 18:18:42 -070038import com.android.internal.os.BackgroundThread;
39
40import java.io.File;
41import java.io.FileDescriptor;
42import java.io.FileInputStream;
43import java.io.FileOutputStream;
44import java.io.IOException;
Dianne Hackborn53459a72013-09-17 17:14:57 -070045import java.io.InputStream;
Dianne Hackbornd2932242013-08-05 18:18:42 -070046import java.io.PrintWriter;
47import java.util.ArrayList;
48import java.util.Collections;
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070049import java.util.List;
Dianne Hackbornd2932242013-08-05 18:18:42 -070050import java.util.concurrent.locks.ReentrantLock;
51
Dianne Hackborn23fb6e82013-08-07 10:08:22 -070052public final class ProcessStatsService extends IProcessStats.Stub {
Dianne Hackbornd2932242013-08-05 18:18:42 -070053 static final String TAG = "ProcessStatsService";
54 static final boolean DEBUG = false;
55
56 // Most data is kept in a sparse data structure: an integer array which integer
57 // holds the type of the entry, and the identifier for a long array that data
58 // exists in and the offset into the array to find it. The constants below
59 // define the encoding of that data in an integer.
60
Dianne Hackborn6d9ef382013-09-23 14:39:23 -070061 static final int MAX_HISTORIC_STATES = 8; // Maximum number of historic states we will keep.
Dianne Hackbornd2932242013-08-05 18:18:42 -070062 static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames.
63 static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames.
64 static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in.
65 static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
Dianne Hackbornd2932242013-08-05 18:18:42 -070066
Dianne Hackborn8a0de582013-08-07 15:22:07 -070067 final ActivityManagerService mAm;
Dianne Hackbornd2932242013-08-05 18:18:42 -070068 final File mBaseDir;
69 ProcessStats mProcessStats;
70 AtomicFile mFile;
71 boolean mCommitPending;
72 boolean mShuttingDown;
73 int mLastMemOnlyState = -1;
74 boolean mMemFactorLowered;
75
76 final ReentrantLock mWriteLock = new ReentrantLock();
77 final Object mPendingWriteLock = new Object();
78 AtomicFile mPendingWriteFile;
79 Parcel mPendingWrite;
80 boolean mPendingWriteCommitted;
81 long mLastWriteTime;
82
Makoto Onuki3ed5be32017-02-01 14:04:47 -080083 /** For CTS to inject the screen state. */
84 @GuardedBy("mAm")
85 Boolean mInjectedScreenState;
86
Dianne Hackborn8a0de582013-08-07 15:22:07 -070087 public ProcessStatsService(ActivityManagerService am, File file) {
88 mAm = am;
Dianne Hackbornd2932242013-08-05 18:18:42 -070089 mBaseDir = file;
90 mBaseDir.mkdirs();
91 mProcessStats = new ProcessStats(true);
92 updateFile();
93 SystemProperties.addChangeCallback(new Runnable() {
94 @Override public void run() {
Dianne Hackborn8a0de582013-08-07 15:22:07 -070095 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -070096 if (mProcessStats.evaluateSystemProperties(false)) {
97 mProcessStats.mFlags |= ProcessStats.FLAG_SYSPROPS;
98 writeStateLocked(true, true);
99 mProcessStats.evaluateSystemProperties(true);
100 }
101 }
102 }
103 });
104 }
105
Dianne Hackbornd94d5332013-10-03 17:32:19 -0700106 @Override
107 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
108 throws RemoteException {
109 try {
110 return super.onTransact(code, data, reply, flags);
111 } catch (RuntimeException e) {
112 if (!(e instanceof SecurityException)) {
113 Slog.wtf(TAG, "Process Stats Crash", e);
114 }
115 throw e;
116 }
117 }
118
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700119 public ProcessState getProcessStateLocked(String packageName,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800120 int uid, int versionCode, String processName) {
121 return mProcessStats.getProcessStateLocked(packageName, uid, versionCode, processName);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700122 }
123
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700124 public ServiceState getServiceStateLocked(String packageName, int uid,
Dianne Hackborn8472e612014-01-23 17:57:20 -0800125 int versionCode, String processName, String className) {
126 return mProcessStats.getServiceStateLocked(packageName, uid, versionCode, processName,
127 className);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700128 }
129
130 public boolean isMemFactorLowered() {
131 return mMemFactorLowered;
132 }
133
134 public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
135 mMemFactorLowered = memFactor < mLastMemOnlyState;
136 mLastMemOnlyState = memFactor;
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800137 if (mInjectedScreenState != null) {
138 screenOn = mInjectedScreenState;
139 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700140 if (screenOn) {
141 memFactor += ProcessStats.ADJ_SCREEN_ON;
142 }
143 if (memFactor != mProcessStats.mMemFactor) {
144 if (mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING) {
145 mProcessStats.mMemFactorDurations[mProcessStats.mMemFactor]
146 += now - mProcessStats.mStartTime;
147 }
148 mProcessStats.mMemFactor = memFactor;
149 mProcessStats.mStartTime = now;
Dianne Hackborn8472e612014-01-23 17:57:20 -0800150 final ArrayMap<String, SparseArray<SparseArray<ProcessStats.PackageState>>> pmap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700151 = mProcessStats.mPackages.getMap();
Dianne Hackborn8472e612014-01-23 17:57:20 -0800152 for (int ipkg=pmap.size()-1; ipkg>=0; ipkg--) {
153 final SparseArray<SparseArray<ProcessStats.PackageState>> uids = pmap.valueAt(ipkg);
154 for (int iuid=uids.size()-1; iuid>=0; iuid--) {
155 final SparseArray<ProcessStats.PackageState> vers = uids.valueAt(iuid);
156 for (int iver=vers.size()-1; iver>=0; iver--) {
157 final ProcessStats.PackageState pkg = vers.valueAt(iver);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700158 final ArrayMap<String, ServiceState> services = pkg.mServices;
Dianne Hackborn8472e612014-01-23 17:57:20 -0800159 for (int isvc=services.size()-1; isvc>=0; isvc--) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700160 final ServiceState service = services.valueAt(isvc);
161 service.setMemFactor(memFactor, now);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700162 }
163 }
164 }
165 }
166 return true;
167 }
168 return false;
169 }
170
171 public int getMemFactorLocked() {
172 return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0;
173 }
174
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700175 public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem,
176 long nativeMem) {
177 mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem);
178 }
179
Dianne Hackbornd2932242013-08-05 18:18:42 -0700180 public boolean shouldWriteNowLocked(long now) {
181 if (now > (mLastWriteTime+WRITE_PERIOD)) {
182 if (SystemClock.elapsedRealtime()
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700183 > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD) &&
184 SystemClock.uptimeMillis()
185 > (mProcessStats.mTimePeriodStartUptime+ProcessStats.COMMIT_UPTIME_PERIOD)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700186 mCommitPending = true;
187 }
188 return true;
189 }
190 return false;
191 }
192
193 public void shutdownLocked() {
194 Slog.w(TAG, "Writing process stats before shutdown...");
195 mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN;
196 writeStateSyncLocked();
197 mShuttingDown = true;
198 }
199
200 public void writeStateAsyncLocked() {
201 writeStateLocked(false);
202 }
203
204 public void writeStateSyncLocked() {
205 writeStateLocked(true);
206 }
207
208 private void writeStateLocked(boolean sync) {
209 if (mShuttingDown) {
210 return;
211 }
212 boolean commitPending = mCommitPending;
213 mCommitPending = false;
214 writeStateLocked(sync, commitPending);
215 }
216
217 public void writeStateLocked(boolean sync, final boolean commit) {
218 synchronized (mPendingWriteLock) {
219 long now = SystemClock.uptimeMillis();
220 if (mPendingWrite == null || !mPendingWriteCommitted) {
221 mPendingWrite = Parcel.obtain();
222 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700223 mProcessStats.mTimePeriodEndUptime = now;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700224 if (commit) {
225 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
226 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700227 mProcessStats.writeToParcel(mPendingWrite, 0);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700228 mPendingWriteFile = new AtomicFile(mFile.getBaseFile());
229 mPendingWriteCommitted = commit;
230 }
231 if (commit) {
232 mProcessStats.resetSafely();
233 updateFile();
234 }
235 mLastWriteTime = SystemClock.uptimeMillis();
Joe Onorato82ba91d2017-04-27 16:18:05 -0700236 if (DEBUG) Slog.d(TAG, "Prepared write state in "
237 + (SystemClock.uptimeMillis()-now) + "ms");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700238 if (!sync) {
239 BackgroundThread.getHandler().post(new Runnable() {
240 @Override public void run() {
241 performWriteState();
242 }
243 });
244 return;
245 }
246 }
247
248 performWriteState();
249 }
250
251 private void updateFile() {
252 mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX
253 + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
254 mLastWriteTime = SystemClock.uptimeMillis();
255 }
256
257 void performWriteState() {
258 if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
259 Parcel data;
260 AtomicFile file;
261 synchronized (mPendingWriteLock) {
262 data = mPendingWrite;
263 file = mPendingWriteFile;
264 mPendingWriteCommitted = false;
265 if (data == null) {
266 return;
267 }
268 mPendingWrite = null;
269 mPendingWriteFile = null;
270 mWriteLock.lock();
271 }
272
273 FileOutputStream stream = null;
274 try {
275 stream = file.startWrite();
276 stream.write(data.marshall());
277 stream.flush();
278 file.finishWrite(stream);
279 if (DEBUG) Slog.d(TAG, "Write completed successfully!");
280 } catch (IOException e) {
281 Slog.w(TAG, "Error writing process statistics", e);
282 file.failWrite(stream);
283 } finally {
284 data.recycle();
285 trimHistoricStatesWriteLocked();
286 mWriteLock.unlock();
287 }
288 }
289
Dianne Hackbornd2932242013-08-05 18:18:42 -0700290 boolean readLocked(ProcessStats stats, AtomicFile file) {
291 try {
292 FileInputStream stream = file.openRead();
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700293 stats.read(stream);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700294 stream.close();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700295 if (stats.mReadError != null) {
296 Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
297 if (DEBUG) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700298 ArrayMap<String, SparseArray<ProcessState>> procMap = stats.mProcesses.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700299 final int NPROC = procMap.size();
300 for (int ip=0; ip<NPROC; ip++) {
301 Slog.w(TAG, "Process: " + procMap.keyAt(ip));
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700302 SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700303 final int NUID = uids.size();
304 for (int iu=0; iu<NUID; iu++) {
305 Slog.w(TAG, " Uid " + uids.keyAt(iu) + ": " + uids.valueAt(iu));
306 }
307 }
Dianne Hackborn8472e612014-01-23 17:57:20 -0800308 ArrayMap<String, SparseArray<SparseArray<ProcessStats.PackageState>>> pkgMap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700309 = stats.mPackages.getMap();
310 final int NPKG = pkgMap.size();
311 for (int ip=0; ip<NPKG; ip++) {
312 Slog.w(TAG, "Package: " + pkgMap.keyAt(ip));
Dianne Hackborn8472e612014-01-23 17:57:20 -0800313 SparseArray<SparseArray<ProcessStats.PackageState>> uids
314 = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700315 final int NUID = uids.size();
316 for (int iu=0; iu<NUID; iu++) {
317 Slog.w(TAG, " Uid: " + uids.keyAt(iu));
Dianne Hackborn8472e612014-01-23 17:57:20 -0800318 SparseArray<ProcessStats.PackageState> vers = uids.valueAt(iu);
319 final int NVERS = vers.size();
320 for (int iv=0; iv<NVERS; iv++) {
321 Slog.w(TAG, " Vers: " + vers.keyAt(iv));
322 ProcessStats.PackageState pkgState = vers.valueAt(iv);
323 final int NPROCS = pkgState.mProcesses.size();
324 for (int iproc=0; iproc<NPROCS; iproc++) {
325 Slog.w(TAG, " Process " + pkgState.mProcesses.keyAt(iproc)
326 + ": " + pkgState.mProcesses.valueAt(iproc));
327 }
328 final int NSRVS = pkgState.mServices.size();
329 for (int isvc=0; isvc<NSRVS; isvc++) {
330 Slog.w(TAG, " Service " + pkgState.mServices.keyAt(isvc)
331 + ": " + pkgState.mServices.valueAt(isvc));
332
333 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700334 }
335 }
336 }
337 }
338 return false;
339 }
340 } catch (Throwable e) {
341 stats.mReadError = "caught exception: " + e;
342 Slog.e(TAG, "Error reading process statistics", e);
343 return false;
344 }
345 return true;
346 }
347
Dianne Hackborn53459a72013-09-17 17:14:57 -0700348 private ArrayList<String> getCommittedFiles(int minNum, boolean inclCurrent,
349 boolean inclCheckedIn) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700350 File[] files = mBaseDir.listFiles();
351 if (files == null || files.length <= minNum) {
352 return null;
353 }
354 ArrayList<String> filesArray = new ArrayList<String>(files.length);
355 String currentFile = mFile.getBaseFile().getPath();
356 if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
357 for (int i=0; i<files.length; i++) {
358 File file = files[i];
359 String fileStr = file.getPath();
360 if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700361 if (!inclCheckedIn && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700362 if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
363 continue;
364 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700365 if (!inclCurrent && fileStr.equals(currentFile)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700366 if (DEBUG) Slog.d(TAG, "Skipping: current stats");
367 continue;
368 }
369 filesArray.add(fileStr);
370 }
371 Collections.sort(filesArray);
372 return filesArray;
373 }
374
375 public void trimHistoricStatesWriteLocked() {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700376 ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700377 if (filesArray == null) {
378 return;
379 }
380 while (filesArray.size() > MAX_HISTORIC_STATES) {
381 String file = filesArray.remove(0);
382 Slog.i(TAG, "Pruning old procstats: " + file);
383 (new File(file)).delete();
384 }
385 }
386
387 boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
388 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
389 boolean sepProcStates, int[] procStates, long now, String reqPackage) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700390 ArrayList<ProcessState> procs = mProcessStats.collectProcessesLocked(
Dianne Hackborn164371f2013-10-01 19:10:13 -0700391 screenStates, memStates, procStates, procStates, now, reqPackage, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700392 if (procs.size() > 0) {
393 if (header != null) {
394 pw.println(header);
395 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700396 DumpUtils.dumpProcessListCsv(pw, procs, sepScreenStates, screenStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700397 sepMemStates, memStates, sepProcStates, procStates, now);
398 return true;
399 }
400 return false;
401 }
402
403 static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
404 String[] outError) {
405 ArrayList<Integer> res = new ArrayList<Integer>();
406 int lastPos = 0;
407 for (int i=0; i<=arg.length(); i++) {
408 char c = i < arg.length() ? arg.charAt(i) : 0;
409 if (c != ',' && c != '+' && c != ' ' && c != 0) {
410 continue;
411 }
412 boolean isSep = c == ',';
413 if (lastPos == 0) {
414 // We now know the type of op.
415 outSep[0] = isSep;
416 } else if (c != 0 && outSep[0] != isSep) {
417 outError[0] = "inconsistent separators (can't mix ',' with '+')";
418 return null;
419 }
420 if (lastPos < (i-1)) {
421 String str = arg.substring(lastPos, i);
422 for (int j=0; j<states.length; j++) {
423 if (str.equals(states[j])) {
424 res.add(j);
425 str = null;
426 break;
427 }
428 }
429 if (str != null) {
430 outError[0] = "invalid word \"" + str + "\"";
431 return null;
432 }
433 }
434 lastPos = i + 1;
435 }
436
437 int[] finalRes = new int[res.size()];
438 for (int i=0; i<res.size(); i++) {
439 finalRes[i] = res.get(i) * mult;
440 }
441 return finalRes;
442 }
443
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700444 public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700445 mAm.mContext.enforceCallingOrSelfPermission(
446 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700447 Parcel current = Parcel.obtain();
riddle_hsu61231a52014-11-15 18:40:08 +0800448 synchronized (mAm) {
449 long now = SystemClock.uptimeMillis();
450 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
451 mProcessStats.mTimePeriodEndUptime = now;
452 mProcessStats.writeToParcel(current, now, 0);
453 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700454 mWriteLock.lock();
455 try {
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700456 if (historic != null) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700457 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700458 if (files != null) {
459 for (int i=files.size()-1; i>=0; i--) {
460 try {
461 ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
462 new File(files.get(i)), ParcelFileDescriptor.MODE_READ_ONLY);
463 historic.add(pfd);
464 } catch (IOException e) {
465 Slog.w(TAG, "Failure opening procstat file " + files.get(i), e);
466 }
467 }
468 }
469 }
470 } finally {
471 mWriteLock.unlock();
472 }
473 return current.marshall();
474 }
475
Dianne Hackborn53459a72013-09-17 17:14:57 -0700476 public ParcelFileDescriptor getStatsOverTime(long minTime) {
477 mAm.mContext.enforceCallingOrSelfPermission(
478 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
riddle_hsu61231a52014-11-15 18:40:08 +0800479 Parcel current = Parcel.obtain();
480 long curTime;
481 synchronized (mAm) {
482 long now = SystemClock.uptimeMillis();
483 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
484 mProcessStats.mTimePeriodEndUptime = now;
485 mProcessStats.writeToParcel(current, now, 0);
486 curTime = mProcessStats.mTimePeriodEndRealtime
487 - mProcessStats.mTimePeriodStartRealtime;
488 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700489 mWriteLock.lock();
490 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700491 if (curTime < minTime) {
492 // Need to add in older stats to reach desired time.
493 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborncb428552013-09-26 11:07:17 -0700494 if (files != null && files.size() > 0) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700495 current.setDataPosition(0);
496 ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current);
497 current.recycle();
Dianne Hackborn59da6792013-10-10 18:27:24 -0700498 int i = files.size()-1;
499 while (i >= 0 && (stats.mTimePeriodEndRealtime
Dianne Hackborn53459a72013-09-17 17:14:57 -0700500 - stats.mTimePeriodStartRealtime) < minTime) {
501 AtomicFile file = new AtomicFile(new File(files.get(i)));
Dianne Hackborn59da6792013-10-10 18:27:24 -0700502 i--;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700503 ProcessStats moreStats = new ProcessStats(false);
504 readLocked(moreStats, file);
505 if (moreStats.mReadError == null) {
506 stats.add(moreStats);
507 StringBuilder sb = new StringBuilder();
508 sb.append("Added stats: ");
509 sb.append(moreStats.mTimePeriodStartClockStr);
510 sb.append(", over ");
511 TimeUtils.formatDuration(moreStats.mTimePeriodEndRealtime
512 - moreStats.mTimePeriodStartRealtime, sb);
513 Slog.i(TAG, sb.toString());
514 } else {
Dianne Hackborn59da6792013-10-10 18:27:24 -0700515 Slog.w(TAG, "Failure reading " + files.get(i+1) + "; "
Dianne Hackborn53459a72013-09-17 17:14:57 -0700516 + moreStats.mReadError);
517 continue;
518 }
519 }
520 current = Parcel.obtain();
521 stats.writeToParcel(current, 0);
522 }
523 }
524 final byte[] outData = current.marshall();
525 current.recycle();
526 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
527 Thread thr = new Thread("ProcessStats pipe output") {
528 public void run() {
529 FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]);
530 try {
531 fout.write(outData);
532 fout.close();
533 } catch (IOException e) {
534 Slog.w(TAG, "Failure writing pipe", e);
535 }
536 }
537 };
538 thr.start();
539 return fds[0];
540 } catch (IOException e) {
541 Slog.w(TAG, "Failed building output pipe", e);
542 } finally {
543 mWriteLock.unlock();
544 }
545 return null;
546 }
547
Dianne Hackborn69cb00b2013-08-09 16:16:56 -0700548 public int getCurrentMemoryState() {
549 synchronized (mAm) {
550 return mLastMemOnlyState;
551 }
552 }
553
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700554 private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
555 String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
556 boolean dumpAll, boolean activeOnly) {
557 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
558 - (ProcessStats.COMMIT_PERIOD/2));
559 if (pfd == null) {
560 pw.println("Unable to build stats!");
561 return;
562 }
563 ProcessStats stats = new ProcessStats(false);
564 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
565 stats.read(stream);
566 if (stats.mReadError != null) {
567 pw.print("Failure reading: "); pw.println(stats.mReadError);
568 return;
569 }
570 if (isCompact) {
571 stats.dumpCheckinLocked(pw, reqPackage);
572 } else {
573 if (dumpDetails || dumpFullDetails) {
574 stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
575 } else {
576 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
577 }
578 }
579 }
580
Dianne Hackbornd2932242013-08-05 18:18:42 -0700581 static private void dumpHelp(PrintWriter pw) {
582 pw.println("Process stats (procstats) dump options:");
583 pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700584 pw.println(" [--details] [--full-details] [--current] [--hours N] [--last N]");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800585 pw.println(" [--max N] --active] [--commit] [--reset] [--clear] [--write] [-h]");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800586 pw.println(" [--start-testing] [--stop-testing] ");
587 pw.println(" [--pretend-screen-on] [--pretend-screen-off] [--stop-pretend-screen]");
588 pw.println(" [<package.name>]");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700589 pw.println(" --checkin: perform a checkin: print and delete old committed states.");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800590 pw.println(" -c: print only state in checkin format.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700591 pw.println(" --csv: output data suitable for putting in a spreadsheet.");
592 pw.println(" --csv-screen: on, off.");
593 pw.println(" --csv-mem: norm, mod, low, crit.");
594 pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
595 pw.println(" service, home, prev, cached");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700596 pw.println(" --details: dump per-package details, not just summary.");
597 pw.println(" --full-details: dump all timing and active state details.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700598 pw.println(" --current: only dump current state.");
Dianne Hackborncb428552013-09-26 11:07:17 -0700599 pw.println(" --hours: aggregate over about N last hours.");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700600 pw.println(" --last: only show the last committed stats at index N (starting at 1).");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800601 pw.println(" --max: for -a, max num of historical batches to print.");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700602 pw.println(" --active: only show currently active processes/services.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700603 pw.println(" --commit: commit current stats to disk and reset to start new stats.");
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700604 pw.println(" --reset: reset current stats, without committing.");
Dianne Hackborn53459a72013-09-17 17:14:57 -0700605 pw.println(" --clear: clear all stats; does both --reset and deletes old stats.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700606 pw.println(" --write: write current in-memory stats to disk.");
607 pw.println(" --read: replace current stats with last-written stats.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800608 pw.println(" --start-testing: clear all stats and starting high frequency pss sampling.");
609 pw.println(" --stop-testing: stop high frequency pss sampling.");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800610 pw.println(" --pretend-screen-on: pretend screen is on.");
611 pw.println(" --pretend-screen-off: pretend screen is off.");
612 pw.println(" --stop-pretend-screen: forget \"pretend screen\" and use the real state.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700613 pw.println(" -a: print everything.");
614 pw.println(" -h: print this help text.");
615 pw.println(" <package.name>: optional name of package to filter output by.");
616 }
617
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700618 @Override
619 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -0600620 if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600621 TAG, pw)) return;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700622
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700623 long ident = Binder.clearCallingIdentity();
624 try {
625 dumpInner(fd, pw, args);
626 } finally {
627 Binder.restoreCallingIdentity(ident);
628 }
629 }
630
631 private void dumpInner(FileDescriptor fd, PrintWriter pw, String[] args) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700632 final long now = SystemClock.uptimeMillis();
633
634 boolean isCheckin = false;
635 boolean isCompact = false;
636 boolean isCsv = false;
637 boolean currentOnly = false;
638 boolean dumpDetails = false;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700639 boolean dumpFullDetails = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700640 boolean dumpAll = false;
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800641 boolean quit = false;
Dianne Hackborncb428552013-09-26 11:07:17 -0700642 int aggregateHours = 0;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700643 int lastIndex = 0;
Dianne Hackbornd052a942014-11-21 15:23:13 -0800644 int maxNum = 2;
Dianne Hackborn164371f2013-10-01 19:10:13 -0700645 boolean activeOnly = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700646 String reqPackage = null;
647 boolean csvSepScreenStats = false;
648 int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
649 boolean csvSepMemStats = false;
650 int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL};
651 boolean csvSepProcStats = true;
652 int[] csvProcStats = ProcessStats.ALL_PROC_STATES;
653 if (args != null) {
654 for (int i=0; i<args.length; i++) {
655 String arg = args[i];
656 if ("--checkin".equals(arg)) {
657 isCheckin = true;
658 } else if ("-c".equals(arg)) {
659 isCompact = true;
660 } else if ("--csv".equals(arg)) {
661 isCsv = true;
662 } else if ("--csv-screen".equals(arg)) {
663 i++;
664 if (i >= args.length) {
665 pw.println("Error: argument required for --csv-screen");
666 dumpHelp(pw);
667 return;
668 }
669 boolean[] sep = new boolean[1];
670 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700671 csvScreenStats = parseStateList(DumpUtils.ADJ_SCREEN_NAMES_CSV,
672 ProcessStats.ADJ_SCREEN_MOD, args[i], sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700673 if (csvScreenStats == null) {
674 pw.println("Error in \"" + args[i] + "\": " + error[0]);
675 dumpHelp(pw);
676 return;
677 }
678 csvSepScreenStats = sep[0];
679 } else if ("--csv-mem".equals(arg)) {
680 i++;
681 if (i >= args.length) {
682 pw.println("Error: argument required for --csv-mem");
683 dumpHelp(pw);
684 return;
685 }
686 boolean[] sep = new boolean[1];
687 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700688 csvMemStats = parseStateList(DumpUtils.ADJ_MEM_NAMES_CSV, 1, args[i],
689 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700690 if (csvMemStats == null) {
691 pw.println("Error in \"" + args[i] + "\": " + error[0]);
692 dumpHelp(pw);
693 return;
694 }
695 csvSepMemStats = sep[0];
696 } else if ("--csv-proc".equals(arg)) {
697 i++;
698 if (i >= args.length) {
699 pw.println("Error: argument required for --csv-proc");
700 dumpHelp(pw);
701 return;
702 }
703 boolean[] sep = new boolean[1];
704 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700705 csvProcStats = parseStateList(DumpUtils.STATE_NAMES_CSV, 1, args[i],
706 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700707 if (csvProcStats == null) {
708 pw.println("Error in \"" + args[i] + "\": " + error[0]);
709 dumpHelp(pw);
710 return;
711 }
712 csvSepProcStats = sep[0];
713 } else if ("--details".equals(arg)) {
714 dumpDetails = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700715 } else if ("--full-details".equals(arg)) {
716 dumpFullDetails = true;
Dianne Hackborncb428552013-09-26 11:07:17 -0700717 } else if ("--hours".equals(arg)) {
718 i++;
719 if (i >= args.length) {
720 pw.println("Error: argument required for --hours");
721 dumpHelp(pw);
722 return;
723 }
724 try {
725 aggregateHours = Integer.parseInt(args[i]);
726 } catch (NumberFormatException e) {
727 pw.println("Error: --hours argument not an int -- " + args[i]);
728 dumpHelp(pw);
729 return;
730 }
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700731 } else if ("--last".equals(arg)) {
732 i++;
733 if (i >= args.length) {
734 pw.println("Error: argument required for --last");
735 dumpHelp(pw);
736 return;
737 }
738 try {
739 lastIndex = Integer.parseInt(args[i]);
740 } catch (NumberFormatException e) {
741 pw.println("Error: --last argument not an int -- " + args[i]);
742 dumpHelp(pw);
743 return;
744 }
Dianne Hackbornd052a942014-11-21 15:23:13 -0800745 } else if ("--max".equals(arg)) {
746 i++;
747 if (i >= args.length) {
748 pw.println("Error: argument required for --max");
749 dumpHelp(pw);
750 return;
751 }
752 try {
753 maxNum = Integer.parseInt(args[i]);
754 } catch (NumberFormatException e) {
755 pw.println("Error: --max argument not an int -- " + args[i]);
756 dumpHelp(pw);
757 return;
758 }
Dianne Hackborn164371f2013-10-01 19:10:13 -0700759 } else if ("--active".equals(arg)) {
760 activeOnly = true;
761 currentOnly = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700762 } else if ("--current".equals(arg)) {
763 currentOnly = true;
764 } else if ("--commit".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700765 synchronized (mAm) {
766 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
767 writeStateLocked(true, true);
768 pw.println("Process stats committed.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800769 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700770 }
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700771 } else if ("--reset".equals(arg)) {
772 synchronized (mAm) {
773 mProcessStats.resetSafely();
774 pw.println("Process stats reset.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800775 quit = true;
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700776 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700777 } else if ("--clear".equals(arg)) {
778 synchronized (mAm) {
779 mProcessStats.resetSafely();
780 ArrayList<String> files = getCommittedFiles(0, true, true);
781 if (files != null) {
782 for (int fi=0; fi<files.size(); fi++) {
783 (new File(files.get(fi))).delete();
784 }
785 }
786 pw.println("All process stats cleared.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800787 quit = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700788 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700789 } else if ("--write".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700790 synchronized (mAm) {
791 writeStateSyncLocked();
792 pw.println("Process stats written.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800793 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700794 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700795 } else if ("--read".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700796 synchronized (mAm) {
797 readLocked(mProcessStats, mFile);
798 pw.println("Process stats read.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800799 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700800 }
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800801 } else if ("--start-testing".equals(arg)) {
802 synchronized (mAm) {
803 mAm.setTestPssMode(true);
804 pw.println("Started high frequency sampling.");
805 quit = true;
806 }
807 } else if ("--stop-testing".equals(arg)) {
808 synchronized (mAm) {
809 mAm.setTestPssMode(false);
810 pw.println("Stopped high frequency sampling.");
811 quit = true;
812 }
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800813 } else if ("--pretend-screen-on".equals(arg)) {
814 synchronized (mAm) {
815 mInjectedScreenState = true;
816 }
817 quit = true;
818 } else if ("--pretend-screen-off".equals(arg)) {
819 synchronized (mAm) {
820 mInjectedScreenState = false;
821 }
822 quit = true;
823 } else if ("--stop-pretend-screen".equals(arg)) {
824 synchronized (mAm) {
825 mInjectedScreenState = null;
826 }
827 quit = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700828 } else if ("-h".equals(arg)) {
829 dumpHelp(pw);
830 return;
831 } else if ("-a".equals(arg)) {
832 dumpDetails = true;
833 dumpAll = true;
834 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
835 pw.println("Unknown option: " + arg);
836 dumpHelp(pw);
837 return;
838 } else {
839 // Not an option, last argument must be a package name.
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800840 reqPackage = arg;
841 // Include all details, since we know we are only going to
842 // be dumping a smaller set of data. In fact only the details
Dianne Hackbornab4a81b2014-10-09 17:59:38 -0700843 // contain per-package data, so this is needed to be able
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800844 // to dump anything at all when filtering by package.
845 dumpDetails = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700846 }
847 }
848 }
849
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800850 if (quit) {
851 return;
852 }
853
Dianne Hackbornd2932242013-08-05 18:18:42 -0700854 if (isCsv) {
855 pw.print("Processes running summed over");
856 if (!csvSepScreenStats) {
857 for (int i=0; i<csvScreenStats.length; i++) {
858 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700859 DumpUtils.printScreenLabelCsv(pw, csvScreenStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700860 }
861 }
862 if (!csvSepMemStats) {
863 for (int i=0; i<csvMemStats.length; i++) {
864 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700865 DumpUtils.printMemLabelCsv(pw, csvMemStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700866 }
867 }
868 if (!csvSepProcStats) {
869 for (int i=0; i<csvProcStats.length; i++) {
870 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700871 pw.print(DumpUtils.STATE_NAMES_CSV[csvProcStats[i]]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700872 }
873 }
874 pw.println();
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700875 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700876 dumpFilteredProcessesCsvLocked(pw, null,
877 csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
878 csvSepProcStats, csvProcStats, now, reqPackage);
879 /*
880 dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
881 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
882 true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
883 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
884 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
885 STATE_PREVIOUS, STATE_CACHED},
886 now, reqPackage);
887 dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
888 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
889 false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
890 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
891 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
892 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
893 STATE_PREVIOUS, STATE_CACHED},
894 now, reqPackage);
895 */
896 }
897 return;
Dianne Hackborncb428552013-09-26 11:07:17 -0700898 } else if (aggregateHours != 0) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800899 pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700900 dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
901 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700902 return;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700903 } else if (lastIndex > 0) {
904 pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":");
905 ArrayList<String> files = getCommittedFiles(0, false, true);
906 if (lastIndex >= files.size()) {
907 pw.print("Only have "); pw.print(files.size()); pw.println(" data sets");
908 return;
909 }
910 AtomicFile file = new AtomicFile(new File(files.get(lastIndex)));
911 ProcessStats processStats = new ProcessStats(false);
912 readLocked(processStats, file);
913 if (processStats.mReadError != null) {
914 if (isCheckin || isCompact) pw.print("err,");
915 pw.print("Failure reading "); pw.print(files.get(lastIndex));
916 pw.print("; "); pw.println(processStats.mReadError);
917 return;
918 }
919 String fileStr = file.getBaseFile().getPath();
920 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
921 if (isCheckin || isCompact) {
922 // Don't really need to lock because we uniquely own this object.
923 processStats.dumpCheckinLocked(pw, reqPackage);
924 } else {
925 pw.print("COMMITTED STATS FROM ");
926 pw.print(processStats.mTimePeriodStartClockStr);
927 if (checkedIn) pw.print(" (checked in)");
928 pw.println(":");
929 if (dumpDetails || dumpFullDetails) {
930 processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
931 activeOnly);
932 if (dumpAll) {
933 pw.print(" mFile="); pw.println(mFile.getBaseFile());
934 }
935 } else {
936 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
937 }
938 }
939 return;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700940 }
941
942 boolean sepNeeded = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800943 if (dumpAll || isCheckin) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700944 mWriteLock.lock();
945 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700946 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700947 if (files != null) {
Dianne Hackbornd052a942014-11-21 15:23:13 -0800948 int start = isCheckin ? 0 : (files.size() - maxNum);
949 if (start < 0) {
950 start = 0;
951 }
952 for (int i=start; i<files.size(); i++) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700953 if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
954 try {
955 AtomicFile file = new AtomicFile(new File(files.get(i)));
956 ProcessStats processStats = new ProcessStats(false);
957 readLocked(processStats, file);
958 if (processStats.mReadError != null) {
959 if (isCheckin || isCompact) pw.print("err,");
960 pw.print("Failure reading "); pw.print(files.get(i));
961 pw.print("; "); pw.println(processStats.mReadError);
962 if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
963 (new File(files.get(i))).delete();
964 continue;
965 }
966 String fileStr = file.getBaseFile().getPath();
967 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
968 if (isCheckin || isCompact) {
969 // Don't really need to lock because we uniquely own this object.
970 processStats.dumpCheckinLocked(pw, reqPackage);
971 } else {
972 if (sepNeeded) {
973 pw.println();
974 } else {
975 sepNeeded = true;
976 }
977 pw.print("COMMITTED STATS FROM ");
978 pw.print(processStats.mTimePeriodStartClockStr);
979 if (checkedIn) pw.print(" (checked in)");
980 pw.println(":");
981 // Don't really need to lock because we uniquely own this object.
Dianne Hackbornae36b232013-09-03 18:12:53 -0700982 // Always dump summary here, dumping all details is just too
983 // much crud.
Dianne Hackborn53459a72013-09-17 17:14:57 -0700984 if (dumpFullDetails) {
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700985 processStats.dumpLocked(pw, reqPackage, now, false, false,
Dianne Hackborn164371f2013-10-01 19:10:13 -0700986 activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700987 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -0700988 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700989 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700990 }
991 if (isCheckin) {
992 // Rename file suffix to mark that it has checked in.
993 file.getBaseFile().renameTo(new File(
994 fileStr + STATE_FILE_CHECKIN_SUFFIX));
995 }
996 } catch (Throwable e) {
997 pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
998 e.printStackTrace(pw);
999 }
1000 }
1001 }
1002 } finally {
1003 mWriteLock.unlock();
1004 }
1005 }
1006 if (!isCheckin) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001007 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001008 if (isCompact) {
1009 mProcessStats.dumpCheckinLocked(pw, reqPackage);
1010 } else {
1011 if (sepNeeded) {
1012 pw.println();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001013 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001014 pw.println("CURRENT STATS:");
Dianne Hackborn53459a72013-09-17 17:14:57 -07001015 if (dumpDetails || dumpFullDetails) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001016 mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
1017 activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001018 if (dumpAll) {
1019 pw.print(" mFile="); pw.println(mFile.getBaseFile());
1020 }
1021 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001022 mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001023 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001024 sepNeeded = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001025 }
1026 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001027 if (!currentOnly) {
1028 if (sepNeeded) {
1029 pw.println();
1030 }
1031 pw.println("AGGREGATED OVER LAST 24 HOURS:");
1032 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
1033 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1034 pw.println();
1035 pw.println("AGGREGATED OVER LAST 3 HOURS:");
1036 dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
1037 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1038 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001039 }
1040 }
1041}