blob: eda04a6a322ac3af5c88be0ba5e466f8d59cd6a9 [file] [log] [blame]
Joe Onorato4eb64fd2016-03-21 15:30:09 -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.internal.app.procstats;
18
Joe Onorato4eb64fd2016-03-21 15:30:09 -070019import android.os.UserHandle;
Yangster-macbac82322018-08-23 14:45:10 -070020import android.service.procstats.ProcessStatsEnums;
Dianne Hackborneaed0ba2018-08-08 17:10:17 -070021import android.service.procstats.ProcessStatsStateProto;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070022import android.util.TimeUtils;
Yi Jin9680cfa2017-09-15 15:14:43 -070023import android.util.proto.ProtoOutputStream;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070024
25import static com.android.internal.app.procstats.ProcessStats.*;
26
Joe Onorato4eb64fd2016-03-21 15:30:09 -070027import java.io.PrintWriter;
28import java.util.ArrayList;
Joe Onorato4eb64fd2016-03-21 15:30:09 -070029
30/**
31 * Utilities for dumping.
32 */
33public final class DumpUtils {
Yi Jin676d1ac2018-01-25 15:40:28 -080034 public static final String[] STATE_NAMES;
Dianne Hackborn7aea7a42018-07-25 08:58:47 -070035 public static final String[] STATE_LABELS;
36 public static final String STATE_LABEL_TOTAL;
37 public static final String STATE_LABEL_CACHED;
Yi Jin676d1ac2018-01-25 15:40:28 -080038 public static final String[] STATE_NAMES_CSV;
39 static final String[] STATE_TAGS;
40 static final int[] STATE_PROTO_ENUMS;
41
42 // Make the mapping easy to update.
43 static {
44 STATE_NAMES = new String[STATE_COUNT];
Dianne Hackborn7aea7a42018-07-25 08:58:47 -070045 STATE_NAMES[STATE_PERSISTENT] = "Persist";
46 STATE_NAMES[STATE_TOP] = "Top";
47 STATE_NAMES[STATE_IMPORTANT_FOREGROUND] = "ImpFg";
48 STATE_NAMES[STATE_IMPORTANT_BACKGROUND] = "ImpBg";
49 STATE_NAMES[STATE_BACKUP] = "Backup";
50 STATE_NAMES[STATE_SERVICE] = "Service";
51 STATE_NAMES[STATE_SERVICE_RESTARTING] = "ServRst";
52 STATE_NAMES[STATE_RECEIVER] = "Receivr";
53 STATE_NAMES[STATE_HEAVY_WEIGHT] = "HeavyWt";
54 STATE_NAMES[STATE_HOME] = "Home";
55 STATE_NAMES[STATE_LAST_ACTIVITY] = "LastAct";
56 STATE_NAMES[STATE_CACHED_ACTIVITY] = "CchAct";
57 STATE_NAMES[STATE_CACHED_ACTIVITY_CLIENT] = "CchCAct";
58 STATE_NAMES[STATE_CACHED_EMPTY] = "CchEmty";
59
60 STATE_LABELS = new String[STATE_COUNT];
61 STATE_LABELS[STATE_PERSISTENT] = "Persistent";
62 STATE_LABELS[STATE_TOP] = " Top";
63 STATE_LABELS[STATE_IMPORTANT_FOREGROUND] = " Imp Fg";
64 STATE_LABELS[STATE_IMPORTANT_BACKGROUND] = " Imp Bg";
65 STATE_LABELS[STATE_BACKUP] = " Backup";
66 STATE_LABELS[STATE_SERVICE] = " Service";
67 STATE_LABELS[STATE_SERVICE_RESTARTING] = "Service Rs";
68 STATE_LABELS[STATE_RECEIVER] = " Receiver";
69 STATE_LABELS[STATE_HEAVY_WEIGHT] = " Heavy Wgt";
70 STATE_LABELS[STATE_HOME] = " (Home)";
71 STATE_LABELS[STATE_LAST_ACTIVITY] = "(Last Act)";
72 STATE_LABELS[STATE_CACHED_ACTIVITY] = " (Cch Act)";
73 STATE_LABELS[STATE_CACHED_ACTIVITY_CLIENT] = "(Cch CAct)";
74 STATE_LABELS[STATE_CACHED_EMPTY] = "(Cch Emty)";
75 STATE_LABEL_CACHED = " (Cached)";
76 STATE_LABEL_TOTAL = " TOTAL";
Yi Jin676d1ac2018-01-25 15:40:28 -080077
78 STATE_NAMES_CSV = new String[STATE_COUNT];
Dianne Hackborn7aea7a42018-07-25 08:58:47 -070079 STATE_NAMES_CSV[STATE_PERSISTENT] = "pers";
80 STATE_NAMES_CSV[STATE_TOP] = "top";
81 STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND] = "impfg";
82 STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND] = "impbg";
83 STATE_NAMES_CSV[STATE_BACKUP] = "backup";
84 STATE_NAMES_CSV[STATE_SERVICE] = "service";
85 STATE_NAMES_CSV[STATE_SERVICE_RESTARTING] = "service-rs";
86 STATE_NAMES_CSV[STATE_RECEIVER] = "receiver";
87 STATE_NAMES_CSV[STATE_HEAVY_WEIGHT] = "heavy";
88 STATE_NAMES_CSV[STATE_HOME] = "home";
89 STATE_NAMES_CSV[STATE_LAST_ACTIVITY] = "lastact";
90 STATE_NAMES_CSV[STATE_CACHED_ACTIVITY] = "cch-activity";
91 STATE_NAMES_CSV[STATE_CACHED_ACTIVITY_CLIENT] = "cch-aclient";
92 STATE_NAMES_CSV[STATE_CACHED_EMPTY] = "cch-empty";
Yi Jin676d1ac2018-01-25 15:40:28 -080093
94 STATE_TAGS = new String[STATE_COUNT];
Dianne Hackborn7aea7a42018-07-25 08:58:47 -070095 STATE_TAGS[STATE_PERSISTENT] = "p";
96 STATE_TAGS[STATE_TOP] = "t";
97 STATE_TAGS[STATE_IMPORTANT_FOREGROUND] = "f";
98 STATE_TAGS[STATE_IMPORTANT_BACKGROUND] = "b";
99 STATE_TAGS[STATE_BACKUP] = "u";
100 STATE_TAGS[STATE_SERVICE] = "s";
101 STATE_TAGS[STATE_SERVICE_RESTARTING] = "x";
102 STATE_TAGS[STATE_RECEIVER] = "r";
103 STATE_TAGS[STATE_HEAVY_WEIGHT] = "w";
104 STATE_TAGS[STATE_HOME] = "h";
105 STATE_TAGS[STATE_LAST_ACTIVITY] = "l";
106 STATE_TAGS[STATE_CACHED_ACTIVITY] = "a";
107 STATE_TAGS[STATE_CACHED_ACTIVITY_CLIENT] = "c";
108 STATE_TAGS[STATE_CACHED_EMPTY] = "e";
Yi Jin676d1ac2018-01-25 15:40:28 -0800109
110 STATE_PROTO_ENUMS = new int[STATE_COUNT];
Yangster-macbac82322018-08-23 14:45:10 -0700111 STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsEnums.PROCESS_STATE_PERSISTENT;
112 STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsEnums.PROCESS_STATE_TOP;
113 STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] =
114 ProcessStatsEnums.PROCESS_STATE_IMPORTANT_FOREGROUND;
115 STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] =
116 ProcessStatsEnums.PROCESS_STATE_IMPORTANT_BACKGROUND;
117 STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsEnums.PROCESS_STATE_BACKUP;
118 STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsEnums.PROCESS_STATE_SERVICE;
119 STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] =
120 ProcessStatsEnums.PROCESS_STATE_SERVICE_RESTARTING;
121 STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsEnums.PROCESS_STATE_RECEIVER;
122 STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsEnums.PROCESS_STATE_HEAVY_WEIGHT;
123 STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsEnums.PROCESS_STATE_HOME;
124 STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsEnums.PROCESS_STATE_LAST_ACTIVITY;
125 STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY] = ProcessStatsEnums.PROCESS_STATE_CACHED_ACTIVITY;
126 STATE_PROTO_ENUMS[STATE_CACHED_ACTIVITY_CLIENT] =
127 ProcessStatsEnums.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
128 STATE_PROTO_ENUMS[STATE_CACHED_EMPTY] = ProcessStatsEnums.PROCESS_STATE_CACHED_EMPTY;
Yi Jin676d1ac2018-01-25 15:40:28 -0800129 }
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700130
131 public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
132 "off", "on"
133 };
134
135 public static final String[] ADJ_MEM_NAMES_CSV = new String[] {
136 "norm", "mod", "low", "crit"
137 };
138
Yi Jin9680cfa2017-09-15 15:14:43 -0700139 // State enum is defined in frameworks/base/core/proto/android/service/procstats.proto
140 // Update states must sync enum definition as well, the ordering must not be changed.
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700141 static final String[] ADJ_SCREEN_TAGS = new String[] {
142 "0", "1"
143 };
144
Yi Jin676d1ac2018-01-25 15:40:28 -0800145 static final int[] ADJ_SCREEN_PROTO_ENUMS = new int[] {
Yangster-macbac82322018-08-23 14:45:10 -0700146 ProcessStatsEnums.SCREEN_STATE_OFF,
147 ProcessStatsEnums.SCREEN_STATE_ON
Yi Jin676d1ac2018-01-25 15:40:28 -0800148 };
149
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700150 static final String[] ADJ_MEM_TAGS = new String[] {
151 "n", "m", "l", "c"
152 };
153
Yi Jin676d1ac2018-01-25 15:40:28 -0800154 static final int[] ADJ_MEM_PROTO_ENUMS = new int[] {
Yangster-macbac82322018-08-23 14:45:10 -0700155 ProcessStatsEnums.MEMORY_STATE_NORMAL,
156 ProcessStatsEnums.MEMORY_STATE_MODERATE,
157 ProcessStatsEnums.MEMORY_STATE_LOW,
158 ProcessStatsEnums.MEMORY_STATE_CRITICAL
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700159 };
160
161 static final String CSV_SEP = "\t";
162
163 /**
164 * No instantiate
165 */
166 private DumpUtils() {
167 }
168
169 public static void printScreenLabel(PrintWriter pw, int offset) {
170 switch (offset) {
171 case ADJ_NOTHING:
172 pw.print(" ");
173 break;
174 case ADJ_SCREEN_OFF:
175 pw.print("SOff/");
176 break;
177 case ADJ_SCREEN_ON:
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700178 pw.print(" SOn/");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700179 break;
180 default:
181 pw.print("????/");
182 break;
183 }
184 }
185
186 public static void printScreenLabelCsv(PrintWriter pw, int offset) {
187 switch (offset) {
188 case ADJ_NOTHING:
189 break;
190 case ADJ_SCREEN_OFF:
191 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
192 break;
193 case ADJ_SCREEN_ON:
194 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
195 break;
196 default:
197 pw.print("???");
198 break;
199 }
200 }
201
202 public static void printMemLabel(PrintWriter pw, int offset, char sep) {
203 switch (offset) {
204 case ADJ_NOTHING:
205 pw.print(" ");
206 if (sep != 0) pw.print(' ');
207 break;
208 case ADJ_MEM_FACTOR_NORMAL:
209 pw.print("Norm");
210 if (sep != 0) pw.print(sep);
211 break;
212 case ADJ_MEM_FACTOR_MODERATE:
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700213 pw.print(" Mod");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700214 if (sep != 0) pw.print(sep);
215 break;
216 case ADJ_MEM_FACTOR_LOW:
Dianne Hackborn7aea7a42018-07-25 08:58:47 -0700217 pw.print(" Low");
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700218 if (sep != 0) pw.print(sep);
219 break;
220 case ADJ_MEM_FACTOR_CRITICAL:
221 pw.print("Crit");
222 if (sep != 0) pw.print(sep);
223 break;
224 default:
225 pw.print("????");
226 if (sep != 0) pw.print(sep);
227 break;
228 }
229 }
230
231 public static void printMemLabelCsv(PrintWriter pw, int offset) {
232 if (offset >= ADJ_MEM_FACTOR_NORMAL) {
233 if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
234 pw.print(ADJ_MEM_NAMES_CSV[offset]);
235 } else {
236 pw.print("???");
237 }
238 }
239 }
240
241 public static void printPercent(PrintWriter pw, double fraction) {
242 fraction *= 100;
243 if (fraction < 1) {
244 pw.print(String.format("%.2f", fraction));
245 } else if (fraction < 10) {
246 pw.print(String.format("%.1f", fraction));
247 } else {
248 pw.print(String.format("%.0f", fraction));
249 }
250 pw.print("%");
251 }
252
253 public static void printProcStateTag(PrintWriter pw, int state) {
254 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT);
255 state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT);
256 printArrayEntry(pw, STATE_TAGS, state, 1);
257 }
258
Yi Jin9680cfa2017-09-15 15:14:43 -0700259 public static void printProcStateTagProto(ProtoOutputStream proto, long screenId, long memId,
260 long stateId, int state) {
Yi Jin676d1ac2018-01-25 15:40:28 -0800261 state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
262 state, ADJ_SCREEN_MOD * STATE_COUNT);
263 state = printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
264 printProto(proto, stateId, STATE_PROTO_ENUMS, state, 1);
Yi Jin9680cfa2017-09-15 15:14:43 -0700265 }
266
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700267 public static void printAdjTag(PrintWriter pw, int state) {
268 state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD);
269 printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
270 }
271
Dianne Hackborneaed0ba2018-08-08 17:10:17 -0700272 public static void printProcStateAdjTagProto(ProtoOutputStream proto, long screenId, long memId,
273 int state) {
274 state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
275 state, ADJ_SCREEN_MOD * STATE_COUNT);
276 printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
277 }
278
279 public static void printProcStateDurationProto(ProtoOutputStream proto, long fieldId,
280 int procState, long duration) {
281 final long stateToken = proto.start(fieldId);
282 DumpUtils.printProto(proto, ProcessStatsStateProto.PROCESS_STATE,
283 DumpUtils.STATE_PROTO_ENUMS, procState, 1);
284 proto.write(ProcessStatsStateProto.DURATION_MS, duration);
285 proto.end(stateToken);
Dianne Hackborneaed0ba2018-08-08 17:10:17 -0700286 }
287
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700288 public static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
289 pw.print(',');
290 printProcStateTag(pw, state);
291 pw.print(':');
292 pw.print(value);
293 }
294
295 public static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
296 pw.print(',');
297 printAdjTag(pw, state);
298 pw.print(':');
299 pw.print(value);
300 }
301
302 public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
303 int curState, long curStartTime, long now) {
304 long totalTime = 0;
305 int printedScreen = -1;
306 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
307 int printedMem = -1;
308 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
309 int state = imem+iscreen;
310 long time = durations[state];
311 String running = "";
312 if (curState == state) {
313 time += now - curStartTime;
314 if (pw != null) {
315 running = " (running)";
316 }
317 }
318 if (time != 0) {
319 if (pw != null) {
320 pw.print(prefix);
321 printScreenLabel(pw, printedScreen != iscreen
322 ? iscreen : STATE_NOTHING);
323 printedScreen = iscreen;
324 printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
325 printedMem = imem;
326 pw.print(": ");
327 TimeUtils.formatDuration(time, pw); pw.println(running);
328 }
329 totalTime += time;
330 }
331 }
332 }
333 if (totalTime != 0 && pw != null) {
334 pw.print(prefix);
335 pw.print(" TOTAL: ");
336 TimeUtils.formatDuration(totalTime, pw);
337 pw.println();
338 }
339 return totalTime;
340 }
341
342 public static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
343 int curState, long curStartTime, long now) {
344 for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
345 for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
346 int state = imem+iscreen;
347 long time = durations[state];
348 if (curState == state) {
349 time += now - curStartTime;
350 }
351 if (time != 0) {
352 printAdjTagAndValue(pw, state, time);
353 }
354 }
355 }
356 }
357
358 private static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
359 int[] memStates, int[] procStates) {
360 final int NS = screenStates != null ? screenStates.length : 1;
361 final int NM = memStates != null ? memStates.length : 1;
362 final int NP = procStates != null ? procStates.length : 1;
363 for (int is=0; is<NS; is++) {
364 for (int im=0; im<NM; im++) {
365 for (int ip=0; ip<NP; ip++) {
366 pw.print(sep);
367 boolean printed = false;
368 if (screenStates != null && screenStates.length > 1) {
369 printScreenLabelCsv(pw, screenStates[is]);
370 printed = true;
371 }
372 if (memStates != null && memStates.length > 1) {
373 if (printed) {
374 pw.print("-");
375 }
376 printMemLabelCsv(pw, memStates[im]);
377 printed = true;
378 }
379 if (procStates != null && procStates.length > 1) {
380 if (printed) {
381 pw.print("-");
382 }
383 pw.print(STATE_NAMES_CSV[procStates[ip]]);
384 }
385 }
386 }
387 }
388 }
389
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700390 public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header,
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700391 ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
392 long now, long totalTime) {
393 for (int i=procs.size()-1; i>=0; i--) {
394 final ProcessState proc = procs.get(i);
Dianne Hackborn2aec55a2018-06-26 10:35:35 -0700395 proc.dumpSummary(pw, prefix, header, screenStates, memStates, procStates, now,
396 totalTime);
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700397 }
398 }
399
400 public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
401 boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
402 boolean sepProcStates, int[] procStates, long now) {
403 pw.print("process");
404 pw.print(CSV_SEP);
405 pw.print("uid");
406 pw.print(CSV_SEP);
407 pw.print("vers");
408 dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
409 sepMemStates ? memStates : null,
410 sepProcStates ? procStates : null);
411 pw.println();
412 for (int i=procs.size()-1; i>=0; i--) {
413 ProcessState proc = procs.get(i);
414 pw.print(proc.getName());
415 pw.print(CSV_SEP);
416 UserHandle.formatUid(pw, proc.getUid());
417 pw.print(CSV_SEP);
418 pw.print(proc.getVersion());
419 proc.dumpCsv(pw, sepScreenStates, screenStates, sepMemStates,
420 memStates, sepProcStates, procStates, now);
421 pw.println();
422 }
423 }
424
425 public static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
426 int index = value/mod;
427 if (index >= 0 && index < array.length) {
428 pw.print(array[index]);
429 } else {
430 pw.print('?');
431 }
432 return value - index*mod;
433 }
434
Yi Jin676d1ac2018-01-25 15:40:28 -0800435 public static int printProto(ProtoOutputStream proto, long fieldId,
436 int[] enums, int value, int mod) {
Yi Jin9680cfa2017-09-15 15:14:43 -0700437 int index = value/mod;
Yi Jin676d1ac2018-01-25 15:40:28 -0800438 if (index >= 0 && index < enums.length) {
439 proto.write(fieldId, enums[index]);
Yi Jin9680cfa2017-09-15 15:14:43 -0700440 } // else enum default is always zero in proto3
441 return value - index*mod;
442 }
443
Joe Onorato4eb64fd2016-03-21 15:30:09 -0700444 public static String collapseString(String pkgName, String itemName) {
445 if (itemName.startsWith(pkgName)) {
446 final int ITEMLEN = itemName.length();
447 final int PKGLEN = pkgName.length();
448 if (ITEMLEN == PKGLEN) {
449 return "";
450 } else if (ITEMLEN >= PKGLEN) {
451 if (itemName.charAt(PKGLEN) == '.') {
452 return itemName.substring(PKGLEN);
453 }
454 }
455 }
456 return itemName;
457 }
458}