blob: edf565abd7df3f93cc2e1bc076fe5d738b08b8d2 [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();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800240 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700241 }
242 mLastWriteTime = SystemClock.uptimeMillis();
Dianne Hackborne17b4452018-01-10 13:15:40 -0800243 totalTime = SystemClock.uptimeMillis() - now;
244 if (DEBUG) Slog.d(TAG, "Prepared write state in " + now + "ms");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700245 if (!sync) {
246 BackgroundThread.getHandler().post(new Runnable() {
247 @Override public void run() {
Dianne Hackborne17b4452018-01-10 13:15:40 -0800248 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700249 }
250 });
251 return;
252 }
253 }
254
Dianne Hackborne17b4452018-01-10 13:15:40 -0800255 performWriteState(totalTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700256 }
257
258 private void updateFile() {
259 mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX
260 + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
261 mLastWriteTime = SystemClock.uptimeMillis();
262 }
263
Dianne Hackborne17b4452018-01-10 13:15:40 -0800264 void performWriteState(long initialTime) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700265 if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
266 Parcel data;
267 AtomicFile file;
268 synchronized (mPendingWriteLock) {
269 data = mPendingWrite;
270 file = mPendingWriteFile;
271 mPendingWriteCommitted = false;
272 if (data == null) {
273 return;
274 }
275 mPendingWrite = null;
276 mPendingWriteFile = null;
277 mWriteLock.lock();
278 }
279
Dianne Hackborne17b4452018-01-10 13:15:40 -0800280 final long startTime = SystemClock.uptimeMillis();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700281 FileOutputStream stream = null;
282 try {
283 stream = file.startWrite();
284 stream.write(data.marshall());
285 stream.flush();
286 file.finishWrite(stream);
Dianne Hackborne17b4452018-01-10 13:15:40 -0800287 com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
288 "procstats", SystemClock.uptimeMillis() - startTime + initialTime);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700289 if (DEBUG) Slog.d(TAG, "Write completed successfully!");
290 } catch (IOException e) {
291 Slog.w(TAG, "Error writing process statistics", e);
292 file.failWrite(stream);
293 } finally {
294 data.recycle();
295 trimHistoricStatesWriteLocked();
296 mWriteLock.unlock();
297 }
298 }
299
Dianne Hackbornd2932242013-08-05 18:18:42 -0700300 boolean readLocked(ProcessStats stats, AtomicFile file) {
301 try {
302 FileInputStream stream = file.openRead();
Dianne Hackborn60444fd2013-08-08 21:57:14 -0700303 stats.read(stream);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700304 stream.close();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700305 if (stats.mReadError != null) {
306 Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
307 if (DEBUG) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700308 ArrayMap<String, SparseArray<ProcessState>> procMap = stats.mProcesses.getMap();
Dianne Hackbornd2932242013-08-05 18:18:42 -0700309 final int NPROC = procMap.size();
310 for (int ip=0; ip<NPROC; ip++) {
311 Slog.w(TAG, "Process: " + procMap.keyAt(ip));
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700312 SparseArray<ProcessState> uids = procMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700313 final int NUID = uids.size();
314 for (int iu=0; iu<NUID; iu++) {
315 Slog.w(TAG, " Uid " + uids.keyAt(iu) + ": " + uids.valueAt(iu));
316 }
317 }
Dianne Hackborn3accca02013-09-20 09:32:11 -0700318 ArrayMap<String, SparseArray<LongSparseArray<ProcessStats.PackageState>>> pkgMap
Dianne Hackbornd2932242013-08-05 18:18:42 -0700319 = stats.mPackages.getMap();
320 final int NPKG = pkgMap.size();
321 for (int ip=0; ip<NPKG; ip++) {
322 Slog.w(TAG, "Package: " + pkgMap.keyAt(ip));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700323 SparseArray<LongSparseArray<ProcessStats.PackageState>> uids
Dianne Hackborn8472e612014-01-23 17:57:20 -0800324 = pkgMap.valueAt(ip);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700325 final int NUID = uids.size();
326 for (int iu=0; iu<NUID; iu++) {
327 Slog.w(TAG, " Uid: " + uids.keyAt(iu));
Dianne Hackborn3accca02013-09-20 09:32:11 -0700328 LongSparseArray<ProcessStats.PackageState> vers = uids.valueAt(iu);
Dianne Hackborn8472e612014-01-23 17:57:20 -0800329 final int NVERS = vers.size();
330 for (int iv=0; iv<NVERS; iv++) {
331 Slog.w(TAG, " Vers: " + vers.keyAt(iv));
332 ProcessStats.PackageState pkgState = vers.valueAt(iv);
333 final int NPROCS = pkgState.mProcesses.size();
334 for (int iproc=0; iproc<NPROCS; iproc++) {
335 Slog.w(TAG, " Process " + pkgState.mProcesses.keyAt(iproc)
336 + ": " + pkgState.mProcesses.valueAt(iproc));
337 }
338 final int NSRVS = pkgState.mServices.size();
339 for (int isvc=0; isvc<NSRVS; isvc++) {
340 Slog.w(TAG, " Service " + pkgState.mServices.keyAt(isvc)
341 + ": " + pkgState.mServices.valueAt(isvc));
342
343 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700344 }
345 }
346 }
347 }
348 return false;
349 }
350 } catch (Throwable e) {
351 stats.mReadError = "caught exception: " + e;
352 Slog.e(TAG, "Error reading process statistics", e);
353 return false;
354 }
355 return true;
356 }
357
Dianne Hackborn53459a72013-09-17 17:14:57 -0700358 private ArrayList<String> getCommittedFiles(int minNum, boolean inclCurrent,
359 boolean inclCheckedIn) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700360 File[] files = mBaseDir.listFiles();
361 if (files == null || files.length <= minNum) {
362 return null;
363 }
364 ArrayList<String> filesArray = new ArrayList<String>(files.length);
365 String currentFile = mFile.getBaseFile().getPath();
366 if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
367 for (int i=0; i<files.length; i++) {
368 File file = files[i];
369 String fileStr = file.getPath();
370 if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700371 if (!inclCheckedIn && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700372 if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
373 continue;
374 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700375 if (!inclCurrent && fileStr.equals(currentFile)) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700376 if (DEBUG) Slog.d(TAG, "Skipping: current stats");
377 continue;
378 }
379 filesArray.add(fileStr);
380 }
381 Collections.sort(filesArray);
382 return filesArray;
383 }
384
385 public void trimHistoricStatesWriteLocked() {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700386 ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700387 if (filesArray == null) {
388 return;
389 }
390 while (filesArray.size() > MAX_HISTORIC_STATES) {
391 String file = filesArray.remove(0);
392 Slog.i(TAG, "Pruning old procstats: " + file);
393 (new File(file)).delete();
394 }
395 }
396
397 boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header,
398 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
399 boolean sepProcStates, int[] procStates, long now, String reqPackage) {
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700400 ArrayList<ProcessState> procs = mProcessStats.collectProcessesLocked(
Dianne Hackborn164371f2013-10-01 19:10:13 -0700401 screenStates, memStates, procStates, procStates, now, reqPackage, false);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700402 if (procs.size() > 0) {
403 if (header != null) {
404 pw.println(header);
405 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700406 DumpUtils.dumpProcessListCsv(pw, procs, sepScreenStates, screenStates,
Dianne Hackbornd2932242013-08-05 18:18:42 -0700407 sepMemStates, memStates, sepProcStates, procStates, now);
408 return true;
409 }
410 return false;
411 }
412
413 static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
414 String[] outError) {
415 ArrayList<Integer> res = new ArrayList<Integer>();
416 int lastPos = 0;
417 for (int i=0; i<=arg.length(); i++) {
418 char c = i < arg.length() ? arg.charAt(i) : 0;
419 if (c != ',' && c != '+' && c != ' ' && c != 0) {
420 continue;
421 }
422 boolean isSep = c == ',';
423 if (lastPos == 0) {
424 // We now know the type of op.
425 outSep[0] = isSep;
426 } else if (c != 0 && outSep[0] != isSep) {
427 outError[0] = "inconsistent separators (can't mix ',' with '+')";
428 return null;
429 }
430 if (lastPos < (i-1)) {
431 String str = arg.substring(lastPos, i);
432 for (int j=0; j<states.length; j++) {
433 if (str.equals(states[j])) {
434 res.add(j);
435 str = null;
436 break;
437 }
438 }
439 if (str != null) {
440 outError[0] = "invalid word \"" + str + "\"";
441 return null;
442 }
443 }
444 lastPos = i + 1;
445 }
446
447 int[] finalRes = new int[res.size()];
448 for (int i=0; i<res.size(); i++) {
449 finalRes[i] = res.get(i) * mult;
450 }
451 return finalRes;
452 }
453
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700454 public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700455 mAm.mContext.enforceCallingOrSelfPermission(
456 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700457 Parcel current = Parcel.obtain();
riddle_hsu61231a52014-11-15 18:40:08 +0800458 synchronized (mAm) {
459 long now = SystemClock.uptimeMillis();
460 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
461 mProcessStats.mTimePeriodEndUptime = now;
462 mProcessStats.writeToParcel(current, now, 0);
463 }
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700464 mWriteLock.lock();
465 try {
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700466 if (historic != null) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700467 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborn23fb6e82013-08-07 10:08:22 -0700468 if (files != null) {
469 for (int i=files.size()-1; i>=0; i--) {
470 try {
471 ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
472 new File(files.get(i)), ParcelFileDescriptor.MODE_READ_ONLY);
473 historic.add(pfd);
474 } catch (IOException e) {
475 Slog.w(TAG, "Failure opening procstat file " + files.get(i), e);
476 }
477 }
478 }
479 }
480 } finally {
481 mWriteLock.unlock();
482 }
483 return current.marshall();
484 }
485
Dianne Hackborn53459a72013-09-17 17:14:57 -0700486 public ParcelFileDescriptor getStatsOverTime(long minTime) {
487 mAm.mContext.enforceCallingOrSelfPermission(
488 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
riddle_hsu61231a52014-11-15 18:40:08 +0800489 Parcel current = Parcel.obtain();
490 long curTime;
491 synchronized (mAm) {
492 long now = SystemClock.uptimeMillis();
493 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
494 mProcessStats.mTimePeriodEndUptime = now;
495 mProcessStats.writeToParcel(current, now, 0);
496 curTime = mProcessStats.mTimePeriodEndRealtime
497 - mProcessStats.mTimePeriodStartRealtime;
498 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700499 mWriteLock.lock();
500 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700501 if (curTime < minTime) {
502 // Need to add in older stats to reach desired time.
503 ArrayList<String> files = getCommittedFiles(0, false, true);
Dianne Hackborncb428552013-09-26 11:07:17 -0700504 if (files != null && files.size() > 0) {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700505 current.setDataPosition(0);
506 ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current);
507 current.recycle();
Dianne Hackborn59da6792013-10-10 18:27:24 -0700508 int i = files.size()-1;
509 while (i >= 0 && (stats.mTimePeriodEndRealtime
Dianne Hackborn53459a72013-09-17 17:14:57 -0700510 - stats.mTimePeriodStartRealtime) < minTime) {
511 AtomicFile file = new AtomicFile(new File(files.get(i)));
Dianne Hackborn59da6792013-10-10 18:27:24 -0700512 i--;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700513 ProcessStats moreStats = new ProcessStats(false);
514 readLocked(moreStats, file);
515 if (moreStats.mReadError == null) {
516 stats.add(moreStats);
517 StringBuilder sb = new StringBuilder();
518 sb.append("Added stats: ");
519 sb.append(moreStats.mTimePeriodStartClockStr);
520 sb.append(", over ");
521 TimeUtils.formatDuration(moreStats.mTimePeriodEndRealtime
522 - moreStats.mTimePeriodStartRealtime, sb);
523 Slog.i(TAG, sb.toString());
524 } else {
Dianne Hackborn59da6792013-10-10 18:27:24 -0700525 Slog.w(TAG, "Failure reading " + files.get(i+1) + "; "
Dianne Hackborn53459a72013-09-17 17:14:57 -0700526 + moreStats.mReadError);
527 continue;
528 }
529 }
530 current = Parcel.obtain();
531 stats.writeToParcel(current, 0);
532 }
533 }
534 final byte[] outData = current.marshall();
535 current.recycle();
536 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
537 Thread thr = new Thread("ProcessStats pipe output") {
538 public void run() {
539 FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]);
540 try {
541 fout.write(outData);
542 fout.close();
543 } catch (IOException e) {
544 Slog.w(TAG, "Failure writing pipe", e);
545 }
546 }
547 };
548 thr.start();
549 return fds[0];
550 } catch (IOException e) {
551 Slog.w(TAG, "Failed building output pipe", e);
552 } finally {
553 mWriteLock.unlock();
554 }
555 return null;
556 }
557
Dianne Hackborn69cb00b2013-08-09 16:16:56 -0700558 public int getCurrentMemoryState() {
559 synchronized (mAm) {
560 return mLastMemOnlyState;
561 }
562 }
563
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700564 private void dumpAggregatedStats(PrintWriter pw, long aggregateHours, long now,
565 String reqPackage, boolean isCompact, boolean dumpDetails, boolean dumpFullDetails,
566 boolean dumpAll, boolean activeOnly) {
567 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
568 - (ProcessStats.COMMIT_PERIOD/2));
569 if (pfd == null) {
570 pw.println("Unable to build stats!");
571 return;
572 }
573 ProcessStats stats = new ProcessStats(false);
574 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
575 stats.read(stream);
576 if (stats.mReadError != null) {
577 pw.print("Failure reading: "); pw.println(stats.mReadError);
578 return;
579 }
580 if (isCompact) {
581 stats.dumpCheckinLocked(pw, reqPackage);
582 } else {
583 if (dumpDetails || dumpFullDetails) {
584 stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
585 } else {
586 stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
587 }
588 }
589 }
590
Dianne Hackbornd2932242013-08-05 18:18:42 -0700591 static private void dumpHelp(PrintWriter pw) {
592 pw.println("Process stats (procstats) dump options:");
593 pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700594 pw.println(" [--details] [--full-details] [--current] [--hours N] [--last N]");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800595 pw.println(" [--max N] --active] [--commit] [--reset] [--clear] [--write] [-h]");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800596 pw.println(" [--start-testing] [--stop-testing] ");
597 pw.println(" [--pretend-screen-on] [--pretend-screen-off] [--stop-pretend-screen]");
598 pw.println(" [<package.name>]");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700599 pw.println(" --checkin: perform a checkin: print and delete old committed states.");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800600 pw.println(" -c: print only state in checkin format.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700601 pw.println(" --csv: output data suitable for putting in a spreadsheet.");
602 pw.println(" --csv-screen: on, off.");
603 pw.println(" --csv-mem: norm, mod, low, crit.");
604 pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
605 pw.println(" service, home, prev, cached");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700606 pw.println(" --details: dump per-package details, not just summary.");
607 pw.println(" --full-details: dump all timing and active state details.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700608 pw.println(" --current: only dump current state.");
Dianne Hackborncb428552013-09-26 11:07:17 -0700609 pw.println(" --hours: aggregate over about N last hours.");
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700610 pw.println(" --last: only show the last committed stats at index N (starting at 1).");
Dianne Hackbornd052a942014-11-21 15:23:13 -0800611 pw.println(" --max: for -a, max num of historical batches to print.");
Dianne Hackborn164371f2013-10-01 19:10:13 -0700612 pw.println(" --active: only show currently active processes/services.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700613 pw.println(" --commit: commit current stats to disk and reset to start new stats.");
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700614 pw.println(" --reset: reset current stats, without committing.");
Dianne Hackborn53459a72013-09-17 17:14:57 -0700615 pw.println(" --clear: clear all stats; does both --reset and deletes old stats.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700616 pw.println(" --write: write current in-memory stats to disk.");
617 pw.println(" --read: replace current stats with last-written stats.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800618 pw.println(" --start-testing: clear all stats and starting high frequency pss sampling.");
619 pw.println(" --stop-testing: stop high frequency pss sampling.");
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800620 pw.println(" --pretend-screen-on: pretend screen is on.");
621 pw.println(" --pretend-screen-off: pretend screen is off.");
622 pw.println(" --stop-pretend-screen: forget \"pretend screen\" and use the real state.");
Dianne Hackbornd2932242013-08-05 18:18:42 -0700623 pw.println(" -a: print everything.");
624 pw.println(" -h: print this help text.");
625 pw.println(" <package.name>: optional name of package to filter output by.");
626 }
627
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700628 @Override
629 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkey6df866a2017-03-31 14:08:23 -0600630 if (!com.android.internal.util.DumpUtils.checkDumpAndUsageStatsPermission(mAm.mContext,
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600631 TAG, pw)) return;
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700632
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700633 long ident = Binder.clearCallingIdentity();
634 try {
Yi Jin9680cfa2017-09-15 15:14:43 -0700635 if (args.length > 0 && "--proto".equals(args[0])) {
636 dumpProto(fd);
637 } else {
638 dumpInner(pw, args);
639 }
Dianne Hackborn08b36a42013-10-09 12:14:11 -0700640 } finally {
641 Binder.restoreCallingIdentity(ident);
642 }
643 }
644
Yi Jin9680cfa2017-09-15 15:14:43 -0700645 private void dumpInner(PrintWriter pw, String[] args) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700646 final long now = SystemClock.uptimeMillis();
647
648 boolean isCheckin = false;
649 boolean isCompact = false;
650 boolean isCsv = false;
651 boolean currentOnly = false;
652 boolean dumpDetails = false;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700653 boolean dumpFullDetails = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700654 boolean dumpAll = false;
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800655 boolean quit = false;
Dianne Hackborncb428552013-09-26 11:07:17 -0700656 int aggregateHours = 0;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700657 int lastIndex = 0;
Dianne Hackbornd052a942014-11-21 15:23:13 -0800658 int maxNum = 2;
Dianne Hackborn164371f2013-10-01 19:10:13 -0700659 boolean activeOnly = false;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700660 String reqPackage = null;
661 boolean csvSepScreenStats = false;
662 int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
663 boolean csvSepMemStats = false;
664 int[] csvMemStats = new int[] { ProcessStats.ADJ_MEM_FACTOR_CRITICAL};
665 boolean csvSepProcStats = true;
666 int[] csvProcStats = ProcessStats.ALL_PROC_STATES;
667 if (args != null) {
668 for (int i=0; i<args.length; i++) {
669 String arg = args[i];
670 if ("--checkin".equals(arg)) {
671 isCheckin = true;
672 } else if ("-c".equals(arg)) {
673 isCompact = true;
674 } else if ("--csv".equals(arg)) {
675 isCsv = true;
676 } else if ("--csv-screen".equals(arg)) {
677 i++;
678 if (i >= args.length) {
679 pw.println("Error: argument required for --csv-screen");
680 dumpHelp(pw);
681 return;
682 }
683 boolean[] sep = new boolean[1];
684 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700685 csvScreenStats = parseStateList(DumpUtils.ADJ_SCREEN_NAMES_CSV,
686 ProcessStats.ADJ_SCREEN_MOD, args[i], sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700687 if (csvScreenStats == null) {
688 pw.println("Error in \"" + args[i] + "\": " + error[0]);
689 dumpHelp(pw);
690 return;
691 }
692 csvSepScreenStats = sep[0];
693 } else if ("--csv-mem".equals(arg)) {
694 i++;
695 if (i >= args.length) {
696 pw.println("Error: argument required for --csv-mem");
697 dumpHelp(pw);
698 return;
699 }
700 boolean[] sep = new boolean[1];
701 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700702 csvMemStats = parseStateList(DumpUtils.ADJ_MEM_NAMES_CSV, 1, args[i],
703 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700704 if (csvMemStats == null) {
705 pw.println("Error in \"" + args[i] + "\": " + error[0]);
706 dumpHelp(pw);
707 return;
708 }
709 csvSepMemStats = sep[0];
710 } else if ("--csv-proc".equals(arg)) {
711 i++;
712 if (i >= args.length) {
713 pw.println("Error: argument required for --csv-proc");
714 dumpHelp(pw);
715 return;
716 }
717 boolean[] sep = new boolean[1];
718 String[] error = new String[1];
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700719 csvProcStats = parseStateList(DumpUtils.STATE_NAMES_CSV, 1, args[i],
720 sep, error);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700721 if (csvProcStats == null) {
722 pw.println("Error in \"" + args[i] + "\": " + error[0]);
723 dumpHelp(pw);
724 return;
725 }
726 csvSepProcStats = sep[0];
727 } else if ("--details".equals(arg)) {
728 dumpDetails = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700729 } else if ("--full-details".equals(arg)) {
730 dumpFullDetails = true;
Dianne Hackborncb428552013-09-26 11:07:17 -0700731 } else if ("--hours".equals(arg)) {
732 i++;
733 if (i >= args.length) {
734 pw.println("Error: argument required for --hours");
735 dumpHelp(pw);
736 return;
737 }
738 try {
739 aggregateHours = Integer.parseInt(args[i]);
740 } catch (NumberFormatException e) {
741 pw.println("Error: --hours argument not an int -- " + args[i]);
742 dumpHelp(pw);
743 return;
744 }
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700745 } else if ("--last".equals(arg)) {
746 i++;
747 if (i >= args.length) {
748 pw.println("Error: argument required for --last");
749 dumpHelp(pw);
750 return;
751 }
752 try {
753 lastIndex = Integer.parseInt(args[i]);
754 } catch (NumberFormatException e) {
755 pw.println("Error: --last argument not an int -- " + args[i]);
756 dumpHelp(pw);
757 return;
758 }
Dianne Hackbornd052a942014-11-21 15:23:13 -0800759 } else if ("--max".equals(arg)) {
760 i++;
761 if (i >= args.length) {
762 pw.println("Error: argument required for --max");
763 dumpHelp(pw);
764 return;
765 }
766 try {
767 maxNum = Integer.parseInt(args[i]);
768 } catch (NumberFormatException e) {
769 pw.println("Error: --max argument not an int -- " + args[i]);
770 dumpHelp(pw);
771 return;
772 }
Dianne Hackborn164371f2013-10-01 19:10:13 -0700773 } else if ("--active".equals(arg)) {
774 activeOnly = true;
775 currentOnly = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700776 } else if ("--current".equals(arg)) {
777 currentOnly = true;
778 } else if ("--commit".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700779 synchronized (mAm) {
780 mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE;
781 writeStateLocked(true, true);
782 pw.println("Process stats committed.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800783 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700784 }
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700785 } else if ("--reset".equals(arg)) {
786 synchronized (mAm) {
787 mProcessStats.resetSafely();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800788 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700789 pw.println("Process stats reset.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800790 quit = true;
Dianne Hackborn0d97cd12013-09-16 19:02:52 -0700791 }
Dianne Hackborn53459a72013-09-17 17:14:57 -0700792 } else if ("--clear".equals(arg)) {
793 synchronized (mAm) {
794 mProcessStats.resetSafely();
Dianne Hackborned0a3222018-02-06 16:01:23 -0800795 mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700796 ArrayList<String> files = getCommittedFiles(0, true, true);
797 if (files != null) {
798 for (int fi=0; fi<files.size(); fi++) {
799 (new File(files.get(fi))).delete();
800 }
801 }
802 pw.println("All process stats cleared.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800803 quit = true;
Dianne Hackborn53459a72013-09-17 17:14:57 -0700804 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700805 } else if ("--write".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700806 synchronized (mAm) {
807 writeStateSyncLocked();
808 pw.println("Process stats written.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800809 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700810 }
Dianne Hackbornd2932242013-08-05 18:18:42 -0700811 } else if ("--read".equals(arg)) {
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700812 synchronized (mAm) {
813 readLocked(mProcessStats, mFile);
814 pw.println("Process stats read.");
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800815 quit = true;
Dianne Hackborn50ef0b62013-09-16 17:40:27 -0700816 }
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800817 } else if ("--start-testing".equals(arg)) {
818 synchronized (mAm) {
819 mAm.setTestPssMode(true);
820 pw.println("Started high frequency sampling.");
821 quit = true;
822 }
823 } else if ("--stop-testing".equals(arg)) {
824 synchronized (mAm) {
825 mAm.setTestPssMode(false);
826 pw.println("Stopped high frequency sampling.");
827 quit = true;
828 }
Makoto Onuki3ed5be32017-02-01 14:04:47 -0800829 } else if ("--pretend-screen-on".equals(arg)) {
830 synchronized (mAm) {
831 mInjectedScreenState = true;
832 }
833 quit = true;
834 } else if ("--pretend-screen-off".equals(arg)) {
835 synchronized (mAm) {
836 mInjectedScreenState = false;
837 }
838 quit = true;
839 } else if ("--stop-pretend-screen".equals(arg)) {
840 synchronized (mAm) {
841 mInjectedScreenState = null;
842 }
843 quit = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700844 } else if ("-h".equals(arg)) {
845 dumpHelp(pw);
846 return;
847 } else if ("-a".equals(arg)) {
848 dumpDetails = true;
849 dumpAll = true;
850 } else if (arg.length() > 0 && arg.charAt(0) == '-'){
851 pw.println("Unknown option: " + arg);
852 dumpHelp(pw);
853 return;
854 } else {
855 // Not an option, last argument must be a package name.
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800856 reqPackage = arg;
857 // Include all details, since we know we are only going to
858 // be dumping a smaller set of data. In fact only the details
Dianne Hackbornab4a81b2014-10-09 17:59:38 -0700859 // contain per-package data, so this is needed to be able
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800860 // to dump anything at all when filtering by package.
861 dumpDetails = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700862 }
863 }
864 }
865
Dianne Hackborn1a4b5a42014-12-08 17:43:31 -0800866 if (quit) {
867 return;
868 }
869
Dianne Hackbornd2932242013-08-05 18:18:42 -0700870 if (isCsv) {
871 pw.print("Processes running summed over");
872 if (!csvSepScreenStats) {
873 for (int i=0; i<csvScreenStats.length; i++) {
874 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700875 DumpUtils.printScreenLabelCsv(pw, csvScreenStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700876 }
877 }
878 if (!csvSepMemStats) {
879 for (int i=0; i<csvMemStats.length; i++) {
880 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700881 DumpUtils.printMemLabelCsv(pw, csvMemStats[i]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700882 }
883 }
884 if (!csvSepProcStats) {
885 for (int i=0; i<csvProcStats.length; i++) {
886 pw.print(" ");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700887 pw.print(DumpUtils.STATE_NAMES_CSV[csvProcStats[i]]);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700888 }
889 }
890 pw.println();
Dianne Hackborn8a0de582013-08-07 15:22:07 -0700891 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700892 dumpFilteredProcessesCsvLocked(pw, null,
893 csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
894 csvSepProcStats, csvProcStats, now, reqPackage);
895 /*
896 dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
897 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
898 true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
899 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
900 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
901 STATE_PREVIOUS, STATE_CACHED},
902 now, reqPackage);
903 dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
904 false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
905 false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
906 ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
907 true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
908 STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
909 STATE_PREVIOUS, STATE_CACHED},
910 now, reqPackage);
911 */
912 }
913 return;
Dianne Hackborncb428552013-09-26 11:07:17 -0700914 } else if (aggregateHours != 0) {
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800915 pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:");
Dianne Hackborn237cefb2013-10-22 18:45:27 -0700916 dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact,
917 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -0700918 return;
Dianne Hackbornf7097a52014-05-13 09:56:14 -0700919 } else if (lastIndex > 0) {
920 pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":");
921 ArrayList<String> files = getCommittedFiles(0, false, true);
922 if (lastIndex >= files.size()) {
923 pw.print("Only have "); pw.print(files.size()); pw.println(" data sets");
924 return;
925 }
926 AtomicFile file = new AtomicFile(new File(files.get(lastIndex)));
927 ProcessStats processStats = new ProcessStats(false);
928 readLocked(processStats, file);
929 if (processStats.mReadError != null) {
930 if (isCheckin || isCompact) pw.print("err,");
931 pw.print("Failure reading "); pw.print(files.get(lastIndex));
932 pw.print("; "); pw.println(processStats.mReadError);
933 return;
934 }
935 String fileStr = file.getBaseFile().getPath();
936 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
937 if (isCheckin || isCompact) {
938 // Don't really need to lock because we uniquely own this object.
939 processStats.dumpCheckinLocked(pw, reqPackage);
940 } else {
941 pw.print("COMMITTED STATS FROM ");
942 pw.print(processStats.mTimePeriodStartClockStr);
943 if (checkedIn) pw.print(" (checked in)");
944 pw.println(":");
945 if (dumpDetails || dumpFullDetails) {
946 processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
947 activeOnly);
948 if (dumpAll) {
949 pw.print(" mFile="); pw.println(mFile.getBaseFile());
950 }
951 } else {
952 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
953 }
954 }
955 return;
Dianne Hackbornd2932242013-08-05 18:18:42 -0700956 }
957
958 boolean sepNeeded = false;
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -0800959 if (dumpAll || isCheckin) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700960 mWriteLock.lock();
961 try {
Dianne Hackborn53459a72013-09-17 17:14:57 -0700962 ArrayList<String> files = getCommittedFiles(0, false, !isCheckin);
Dianne Hackbornd2932242013-08-05 18:18:42 -0700963 if (files != null) {
Dianne Hackbornd052a942014-11-21 15:23:13 -0800964 int start = isCheckin ? 0 : (files.size() - maxNum);
965 if (start < 0) {
966 start = 0;
967 }
968 for (int i=start; i<files.size(); i++) {
Dianne Hackbornd2932242013-08-05 18:18:42 -0700969 if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
970 try {
971 AtomicFile file = new AtomicFile(new File(files.get(i)));
972 ProcessStats processStats = new ProcessStats(false);
973 readLocked(processStats, file);
974 if (processStats.mReadError != null) {
975 if (isCheckin || isCompact) pw.print("err,");
976 pw.print("Failure reading "); pw.print(files.get(i));
977 pw.print("; "); pw.println(processStats.mReadError);
978 if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
979 (new File(files.get(i))).delete();
980 continue;
981 }
982 String fileStr = file.getBaseFile().getPath();
983 boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
984 if (isCheckin || isCompact) {
985 // Don't really need to lock because we uniquely own this object.
986 processStats.dumpCheckinLocked(pw, reqPackage);
987 } else {
988 if (sepNeeded) {
989 pw.println();
990 } else {
991 sepNeeded = true;
992 }
993 pw.print("COMMITTED STATS FROM ");
994 pw.print(processStats.mTimePeriodStartClockStr);
995 if (checkedIn) pw.print(" (checked in)");
996 pw.println(":");
997 // Don't really need to lock because we uniquely own this object.
Dianne Hackbornae36b232013-09-03 18:12:53 -0700998 // Always dump summary here, dumping all details is just too
999 // much crud.
Dianne Hackborn53459a72013-09-17 17:14:57 -07001000 if (dumpFullDetails) {
Dianne Hackbornf7097a52014-05-13 09:56:14 -07001001 processStats.dumpLocked(pw, reqPackage, now, false, false,
Dianne Hackborn164371f2013-10-01 19:10:13 -07001002 activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001003 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001004 processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackborn53459a72013-09-17 17:14:57 -07001005 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001006 }
1007 if (isCheckin) {
1008 // Rename file suffix to mark that it has checked in.
1009 file.getBaseFile().renameTo(new File(
1010 fileStr + STATE_FILE_CHECKIN_SUFFIX));
1011 }
1012 } catch (Throwable e) {
1013 pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
1014 e.printStackTrace(pw);
1015 }
1016 }
1017 }
1018 } finally {
1019 mWriteLock.unlock();
1020 }
1021 }
1022 if (!isCheckin) {
Dianne Hackborn8a0de582013-08-07 15:22:07 -07001023 synchronized (mAm) {
Dianne Hackbornd2932242013-08-05 18:18:42 -07001024 if (isCompact) {
1025 mProcessStats.dumpCheckinLocked(pw, reqPackage);
1026 } else {
1027 if (sepNeeded) {
1028 pw.println();
Dianne Hackbornd2932242013-08-05 18:18:42 -07001029 }
Dianne Hackborndaa0d5c2013-11-06 16:30:29 -08001030 pw.println("CURRENT STATS:");
Dianne Hackborn53459a72013-09-17 17:14:57 -07001031 if (dumpDetails || dumpFullDetails) {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001032 mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
1033 activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001034 if (dumpAll) {
1035 pw.print(" mFile="); pw.println(mFile.getBaseFile());
1036 }
1037 } else {
Dianne Hackborn164371f2013-10-01 19:10:13 -07001038 mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
Dianne Hackbornd2932242013-08-05 18:18:42 -07001039 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001040 sepNeeded = true;
Dianne Hackbornd2932242013-08-05 18:18:42 -07001041 }
1042 }
Dianne Hackbornd052a942014-11-21 15:23:13 -08001043 if (!currentOnly) {
1044 if (sepNeeded) {
1045 pw.println();
1046 }
1047 pw.println("AGGREGATED OVER LAST 24 HOURS:");
1048 dumpAggregatedStats(pw, 24, now, reqPackage, isCompact,
1049 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1050 pw.println();
1051 pw.println("AGGREGATED OVER LAST 3 HOURS:");
1052 dumpAggregatedStats(pw, 3, now, reqPackage, isCompact,
1053 dumpDetails, dumpFullDetails, dumpAll, activeOnly);
1054 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001055 }
1056 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001057
Yi Jin676d1ac2018-01-25 15:40:28 -08001058 private void dumpAggregatedStats(ProtoOutputStream proto, long fieldId, int aggregateHours, long now) {
Yi Jin9680cfa2017-09-15 15:14:43 -07001059 ParcelFileDescriptor pfd = getStatsOverTime(aggregateHours*60*60*1000
1060 - (ProcessStats.COMMIT_PERIOD/2));
1061 if (pfd == null) {
1062 return;
1063 }
1064 ProcessStats stats = new ProcessStats(false);
1065 InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
1066 stats.read(stream);
1067 if (stats.mReadError != null) {
1068 return;
1069 }
Yi Jin676d1ac2018-01-25 15:40:28 -08001070 stats.writeToProto(proto, fieldId, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001071 }
1072
1073 private void dumpProto(FileDescriptor fd) {
1074 final ProtoOutputStream proto = new ProtoOutputStream(fd);
1075
1076 // dump current procstats
Yi Jin9680cfa2017-09-15 15:14:43 -07001077 long now;
1078 synchronized (mAm) {
1079 now = SystemClock.uptimeMillis();
Yi Jin676d1ac2018-01-25 15:40:28 -08001080 mProcessStats.writeToProto(proto,ProcessStatsServiceDumpProto.PROCSTATS_NOW, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001081 }
Yi Jin9680cfa2017-09-15 15:14:43 -07001082
1083 // aggregated over last 3 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001084 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_3HRS, 3, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001085
1086 // aggregated over last 24 hours procstats
Yi Jin676d1ac2018-01-25 15:40:28 -08001087 dumpAggregatedStats(proto, ProcessStatsServiceDumpProto.PROCSTATS_OVER_24HRS, 24, now);
Yi Jin9680cfa2017-09-15 15:14:43 -07001088
1089 proto.flush();
1090 }
Dianne Hackbornd2932242013-08-05 18:18:42 -07001091}