blob: ba96b7494bba5b0a1633addf751ea274e50c2474 [file] [log] [blame]
Dianne Hackborn807de782016-04-07 17:54:41 -07001/*
2 * Copyright (C) 2016 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.job;
18
19import android.app.job.JobInfo;
20import android.os.SystemClock;
21import android.os.UserHandle;
22import android.text.format.DateFormat;
23import android.util.ArrayMap;
24import android.util.SparseArray;
25import android.util.TimeUtils;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070026import com.android.internal.util.RingBufferIndices;
Dianne Hackborn807de782016-04-07 17:54:41 -070027import com.android.server.job.controllers.JobStatus;
28
29import java.io.PrintWriter;
30
31public final class JobPackageTracker {
32 // We batch every 30 minutes.
33 static final long BATCHING_TIME = 30*60*1000;
34 // Number of historical data sets we keep.
35 static final int NUM_HISTORY = 5;
36
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070037 private static final int EVENT_BUFFER_SIZE = 100;
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -070038
39 public static final int EVENT_NULL = 0;
40 public static final int EVENT_START_JOB = 1;
41 public static final int EVENT_STOP_JOB = 2;
42
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070043 private final RingBufferIndices mEventIndices = new RingBufferIndices(EVENT_BUFFER_SIZE);
44 private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
45 private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
46 private final int[] mEventUids = new int[EVENT_BUFFER_SIZE];
47 private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -070048
49 public void addEvent(int cmd, int uid, String tag) {
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070050 int index = mEventIndices.add();
51 mEventCmds[index] = cmd;
52 mEventTimes[index] = SystemClock.elapsedRealtime();
53 mEventUids[index] = uid;
54 mEventTags[index] = tag;
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -070055 }
56
Dianne Hackborn807de782016-04-07 17:54:41 -070057 DataSet mCurDataSet = new DataSet();
58 DataSet[] mLastDataSets = new DataSet[NUM_HISTORY];
59
60 final static class PackageEntry {
61 long pastActiveTime;
62 long activeStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070063 int activeNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -070064 int activeCount;
65 boolean hadActive;
66 long pastActiveTopTime;
67 long activeTopStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070068 int activeTopNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -070069 int activeTopCount;
70 boolean hadActiveTop;
71 long pastPendingTime;
72 long pendingStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070073 int pendingNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -070074 int pendingCount;
75 boolean hadPending;
76
77 public long getActiveTime(long now) {
78 long time = pastActiveTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070079 if (activeNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -070080 time += now - activeStartTime;
81 }
82 return time;
83 }
84
85 public long getActiveTopTime(long now) {
86 long time = pastActiveTopTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070087 if (activeTopNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -070088 time += now - activeTopStartTime;
89 }
90 return time;
91 }
92
93 public long getPendingTime(long now) {
94 long time = pastPendingTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -070095 if (pendingNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -070096 time += now - pendingStartTime;
97 }
98 return time;
99 }
100 }
101
102 final static class DataSet {
103 final SparseArray<ArrayMap<String, PackageEntry>> mEntries = new SparseArray<>();
104 final long mStartUptimeTime;
105 final long mStartElapsedTime;
106 final long mStartClockTime;
107 long mSummedTime;
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700108 int mMaxTotalActive;
109 int mMaxFgActive;
Dianne Hackborn807de782016-04-07 17:54:41 -0700110
111 public DataSet(DataSet otherTimes) {
112 mStartUptimeTime = otherTimes.mStartUptimeTime;
113 mStartElapsedTime = otherTimes.mStartElapsedTime;
114 mStartClockTime = otherTimes.mStartClockTime;
115 }
116
117 public DataSet() {
118 mStartUptimeTime = SystemClock.uptimeMillis();
119 mStartElapsedTime = SystemClock.elapsedRealtime();
120 mStartClockTime = System.currentTimeMillis();
121 }
122
123 private PackageEntry getOrCreateEntry(int uid, String pkg) {
124 ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
125 if (uidMap == null) {
126 uidMap = new ArrayMap<>();
127 mEntries.put(uid, uidMap);
128 }
129 PackageEntry entry = uidMap.get(pkg);
130 if (entry == null) {
131 entry = new PackageEntry();
132 uidMap.put(pkg, entry);
133 }
134 return entry;
135 }
136
137 public PackageEntry getEntry(int uid, String pkg) {
138 ArrayMap<String, PackageEntry> uidMap = mEntries.get(uid);
139 if (uidMap == null) {
140 return null;
141 }
142 return uidMap.get(pkg);
143 }
144
145 long getTotalTime(long now) {
146 if (mSummedTime > 0) {
147 return mSummedTime;
148 }
149 return now - mStartUptimeTime;
150 }
151
152 void incPending(int uid, String pkg, long now) {
153 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700154 if (pe.pendingNesting == 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700155 pe.pendingStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700156 pe.pendingCount++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700157 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700158 pe.pendingNesting++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700159 }
160
161 void decPending(int uid, String pkg, long now) {
162 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700163 if (pe.pendingNesting == 1) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700164 pe.pastPendingTime += now - pe.pendingStartTime;
165 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700166 pe.pendingNesting--;
Dianne Hackborn807de782016-04-07 17:54:41 -0700167 }
168
169 void incActive(int uid, String pkg, long now) {
170 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700171 if (pe.activeNesting == 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700172 pe.activeStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700173 pe.activeCount++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700174 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700175 pe.activeNesting++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700176 }
177
178 void decActive(int uid, String pkg, long now) {
179 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700180 if (pe.activeNesting == 1) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700181 pe.pastActiveTime += now - pe.activeStartTime;
182 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700183 pe.activeNesting--;
Dianne Hackborn807de782016-04-07 17:54:41 -0700184 }
185
186 void incActiveTop(int uid, String pkg, long now) {
187 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700188 if (pe.activeTopNesting == 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700189 pe.activeTopStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700190 pe.activeTopCount++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700191 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700192 pe.activeTopNesting++;
Dianne Hackborn807de782016-04-07 17:54:41 -0700193 }
194
195 void decActiveTop(int uid, String pkg, long now) {
196 PackageEntry pe = getOrCreateEntry(uid, pkg);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700197 if (pe.activeTopNesting == 1) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700198 pe.pastActiveTopTime += now - pe.activeTopStartTime;
199 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700200 pe.activeTopNesting--;
Dianne Hackborn807de782016-04-07 17:54:41 -0700201 }
202
203 void finish(DataSet next, long now) {
204 for (int i = mEntries.size() - 1; i >= 0; i--) {
205 ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
206 for (int j = uidMap.size() - 1; j >= 0; j--) {
207 PackageEntry pe = uidMap.valueAt(j);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700208 if (pe.activeNesting > 0 || pe.activeTopNesting > 0 || pe.pendingNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700209 // Propagate existing activity in to next data set.
210 PackageEntry nextPe = next.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
211 nextPe.activeStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700212 nextPe.activeNesting = pe.activeNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -0700213 nextPe.activeTopStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700214 nextPe.activeTopNesting = pe.activeTopNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -0700215 nextPe.pendingStartTime = now;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700216 nextPe.pendingNesting = pe.pendingNesting;
Dianne Hackborn807de782016-04-07 17:54:41 -0700217 // Finish it off.
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700218 if (pe.activeNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700219 pe.pastActiveTime += now - pe.activeStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700220 pe.activeNesting = 0;
Dianne Hackborn807de782016-04-07 17:54:41 -0700221 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700222 if (pe.activeTopNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700223 pe.pastActiveTopTime += now - pe.activeTopStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700224 pe.activeTopNesting = 0;
Dianne Hackborn807de782016-04-07 17:54:41 -0700225 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700226 if (pe.pendingNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700227 pe.pastPendingTime += now - pe.pendingStartTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700228 pe.pendingNesting = 0;
Dianne Hackborn807de782016-04-07 17:54:41 -0700229 }
230 }
231 }
232 }
233 }
234
235 void addTo(DataSet out, long now) {
236 out.mSummedTime += getTotalTime(now);
237 for (int i = mEntries.size() - 1; i >= 0; i--) {
238 ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
239 for (int j = uidMap.size() - 1; j >= 0; j--) {
240 PackageEntry pe = uidMap.valueAt(j);
241 PackageEntry outPe = out.getOrCreateEntry(mEntries.keyAt(i), uidMap.keyAt(j));
242 outPe.pastActiveTime += pe.pastActiveTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700243 outPe.activeCount += pe.activeCount;
Dianne Hackborn807de782016-04-07 17:54:41 -0700244 outPe.pastActiveTopTime += pe.pastActiveTopTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700245 outPe.activeTopCount += pe.activeTopCount;
Dianne Hackborn807de782016-04-07 17:54:41 -0700246 outPe.pastPendingTime += pe.pastPendingTime;
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700247 outPe.pendingCount += pe.pendingCount;
248 if (pe.activeNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700249 outPe.pastActiveTime += now - pe.activeStartTime;
250 outPe.hadActive = true;
251 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700252 if (pe.activeTopNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700253 outPe.pastActiveTopTime += now - pe.activeTopStartTime;
254 outPe.hadActiveTop = true;
255 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700256 if (pe.pendingNesting > 0) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700257 outPe.pastPendingTime += now - pe.pendingStartTime;
258 outPe.hadPending = true;
259 }
260 }
261 }
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700262 if (mMaxTotalActive > out.mMaxTotalActive) {
263 out.mMaxTotalActive = mMaxTotalActive;
264 }
265 if (mMaxFgActive > out.mMaxFgActive) {
266 out.mMaxFgActive = mMaxFgActive;
267 }
Dianne Hackborn807de782016-04-07 17:54:41 -0700268 }
269
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700270 void printDuration(PrintWriter pw, long period, long duration, int count, String suffix) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700271 float fraction = duration / (float) period;
272 int percent = (int) ((fraction * 100) + .5f);
273 if (percent > 0) {
274 pw.print(" ");
275 pw.print(percent);
276 pw.print("% ");
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700277 pw.print(count);
278 pw.print("x ");
279 pw.print(suffix);
280 } else if (count > 0) {
281 pw.print(" ");
282 pw.print(count);
283 pw.print("x ");
Dianne Hackborn807de782016-04-07 17:54:41 -0700284 pw.print(suffix);
285 }
286 }
287
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700288 void dump(PrintWriter pw, String header, String prefix, long now, long nowEllapsed,
289 int filterUid) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700290 final long period = getTotalTime(now);
291 pw.print(prefix); pw.print(header); pw.print(" at ");
292 pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", mStartClockTime).toString());
293 pw.print(" (");
294 TimeUtils.formatDuration(mStartElapsedTime, nowEllapsed, pw);
295 pw.print(") over ");
296 TimeUtils.formatDuration(period, pw);
297 pw.println(":");
298 final int NE = mEntries.size();
299 for (int i = 0; i < NE; i++) {
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700300 int uid = mEntries.keyAt(i);
301 if (filterUid != -1 && filterUid != UserHandle.getAppId(uid)) {
302 continue;
303 }
Dianne Hackborn807de782016-04-07 17:54:41 -0700304 ArrayMap<String, PackageEntry> uidMap = mEntries.valueAt(i);
305 final int NP = uidMap.size();
306 for (int j = 0; j < NP; j++) {
307 PackageEntry pe = uidMap.valueAt(j);
308 pw.print(prefix); pw.print(" ");
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700309 UserHandle.formatUid(pw, uid);
Dianne Hackborn807de782016-04-07 17:54:41 -0700310 pw.print(" / "); pw.print(uidMap.keyAt(j));
311 pw.print(":");
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700312 printDuration(pw, period, pe.getPendingTime(now), pe.pendingCount, "pending");
313 printDuration(pw, period, pe.getActiveTime(now), pe.activeCount, "active");
314 printDuration(pw, period, pe.getActiveTopTime(now), pe.activeTopCount,
315 "active-top");
316 if (pe.pendingNesting > 0 || pe.hadPending) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700317 pw.print(" (pending)");
318 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700319 if (pe.activeNesting > 0 || pe.hadActive) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700320 pw.print(" (active)");
321 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700322 if (pe.activeTopNesting > 0 || pe.hadActiveTop) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700323 pw.print(" (active-top)");
324 }
325 pw.println();
326 }
327 }
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700328 pw.print(prefix); pw.print(" Max concurrency: ");
329 pw.print(mMaxTotalActive); pw.print(" total, ");
330 pw.print(mMaxFgActive); pw.println(" foreground");
Dianne Hackborn807de782016-04-07 17:54:41 -0700331 }
332 }
333
334 void rebatchIfNeeded(long now) {
335 long totalTime = mCurDataSet.getTotalTime(now);
336 if (totalTime > BATCHING_TIME) {
337 DataSet last = mCurDataSet;
338 last.mSummedTime = totalTime;
339 mCurDataSet = new DataSet();
340 last.finish(mCurDataSet, now);
341 System.arraycopy(mLastDataSets, 0, mLastDataSets, 1, mLastDataSets.length-1);
342 mLastDataSets[0] = last;
343 }
344 }
345
346 public void notePending(JobStatus job) {
347 final long now = SystemClock.uptimeMillis();
348 rebatchIfNeeded(now);
349 mCurDataSet.incPending(job.getSourceUid(), job.getSourcePackageName(), now);
350 }
351
352 public void noteNonpending(JobStatus job) {
353 final long now = SystemClock.uptimeMillis();
354 mCurDataSet.decPending(job.getSourceUid(), job.getSourcePackageName(), now);
355 rebatchIfNeeded(now);
356 }
357
358 public void noteActive(JobStatus job) {
359 final long now = SystemClock.uptimeMillis();
360 rebatchIfNeeded(now);
361 if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
362 mCurDataSet.incActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
363 } else {
364 mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now);
365 }
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700366 addEvent(EVENT_START_JOB, job.getSourceUid(), job.getBatteryName());
Dianne Hackborn807de782016-04-07 17:54:41 -0700367 }
368
369 public void noteInactive(JobStatus job) {
370 final long now = SystemClock.uptimeMillis();
371 if (job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
372 mCurDataSet.decActiveTop(job.getSourceUid(), job.getSourcePackageName(), now);
373 } else {
374 mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now);
375 }
376 rebatchIfNeeded(now);
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700377 addEvent(EVENT_STOP_JOB, job.getSourceUid(), job.getBatteryName());
Dianne Hackborn807de782016-04-07 17:54:41 -0700378 }
379
Dianne Hackborne9a988c2016-05-27 17:59:40 -0700380 public void noteConcurrency(int totalActive, int fgActive) {
381 if (totalActive > mCurDataSet.mMaxTotalActive) {
382 mCurDataSet.mMaxTotalActive = totalActive;
383 }
384 if (fgActive > mCurDataSet.mMaxFgActive) {
385 mCurDataSet.mMaxFgActive = fgActive;
386 }
387 }
388
Dianne Hackborn807de782016-04-07 17:54:41 -0700389 public float getLoadFactor(JobStatus job) {
390 final int uid = job.getSourceUid();
391 final String pkg = job.getSourcePackageName();
392 PackageEntry cur = mCurDataSet.getEntry(uid, pkg);
393 PackageEntry last = mLastDataSets[0] != null ? mLastDataSets[0].getEntry(uid, pkg) : null;
394 if (cur == null && last == null) {
395 return 0;
396 }
397 final long now = SystemClock.uptimeMillis();
398 long time = cur.getActiveTime(now) + cur.getPendingTime(now);
399 long period = mCurDataSet.getTotalTime(now);
400 if (last != null) {
401 time += last.getActiveTime(now) + last.getPendingTime(now);
402 period += mLastDataSets[0].getTotalTime(now);
403 }
404 return time / (float)period;
405 }
406
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700407 public void dump(PrintWriter pw, String prefix, int filterUid) {
Dianne Hackborn807de782016-04-07 17:54:41 -0700408 final long now = SystemClock.uptimeMillis();
409 final long nowEllapsed = SystemClock.elapsedRealtime();
410 final DataSet total;
411 if (mLastDataSets[0] != null) {
412 total = new DataSet(mLastDataSets[0]);
413 mLastDataSets[0].addTo(total, now);
414 } else {
415 total = new DataSet(mCurDataSet);
416 }
417 mCurDataSet.addTo(total, now);
418 for (int i = 1; i < mLastDataSets.length; i++) {
419 if (mLastDataSets[i] != null) {
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700420 mLastDataSets[i].dump(pw, "Historical stats", prefix, now, nowEllapsed, filterUid);
Dianne Hackborn807de782016-04-07 17:54:41 -0700421 pw.println();
422 }
423 }
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700424 total.dump(pw, "Current stats", prefix, now, nowEllapsed, filterUid);
425 }
426
427 public boolean dumpHistory(PrintWriter pw, String prefix, int filterUid) {
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700428 final int size = mEventIndices.size();
429 if (size <= 0) {
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700430 return false;
431 }
432 pw.println(" Job history:");
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700433 final long now = SystemClock.elapsedRealtime();
434 for (int i=0; i<size; i++) {
435 final int index = mEventIndices.indexOf(i);
436 final int uid = mEventUids[index];
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700437 if (filterUid != -1 && filterUid != UserHandle.getAppId(filterUid)) {
438 continue;
439 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700440 final int cmd = mEventCmds[index];
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700441 if (cmd == EVENT_NULL) {
442 continue;
443 }
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700444 final String label;
445 switch (mEventCmds[index]) {
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700446 case EVENT_START_JOB: label = "START"; break;
447 case EVENT_STOP_JOB: label = " STOP"; break;
448 default: label = " ??"; break;
449 }
450 pw.print(prefix);
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700451 TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700452 pw.print(" ");
453 pw.print(label);
454 pw.print(": ");
455 UserHandle.formatUid(pw, uid);
456 pw.print(" ");
Dianne Hackborn5a969aa2016-05-04 17:18:19 -0700457 pw.println(mEventTags[index]);
Dianne Hackbornef3aa6e2016-04-29 18:18:08 -0700458 }
459 return true;
Dianne Hackborn807de782016-04-07 17:54:41 -0700460 }
461}