1 /*
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 
17 package com.android.internal.app.procstats;
18 
19 import static com.android.internal.app.procstats.ProcessStats.ADJ_COUNT;
20 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_COUNT;
21 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
22 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
23 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_MODERATE;
24 import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_NORMAL;
25 import static com.android.internal.app.procstats.ProcessStats.ADJ_NOTHING;
26 import static com.android.internal.app.procstats.ProcessStats.ADJ_SCREEN_MOD;
27 import static com.android.internal.app.procstats.ProcessStats.ADJ_SCREEN_OFF;
28 import static com.android.internal.app.procstats.ProcessStats.ADJ_SCREEN_ON;
29 import static com.android.internal.app.procstats.ProcessStats.STATE_BACKUP;
30 import static com.android.internal.app.procstats.ProcessStats.STATE_BOUND_FGS;
31 import static com.android.internal.app.procstats.ProcessStats.STATE_BOUND_TOP;
32 import static com.android.internal.app.procstats.ProcessStats.STATE_CACHED;
33 import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
34 import static com.android.internal.app.procstats.ProcessStats.STATE_FGS;
35 import static com.android.internal.app.procstats.ProcessStats.STATE_FROZEN;
36 import static com.android.internal.app.procstats.ProcessStats.STATE_HEAVY_WEIGHT;
37 import static com.android.internal.app.procstats.ProcessStats.STATE_HOME;
38 import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_BACKGROUND;
39 import static com.android.internal.app.procstats.ProcessStats.STATE_IMPORTANT_FOREGROUND;
40 import static com.android.internal.app.procstats.ProcessStats.STATE_LAST_ACTIVITY;
41 import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
42 import static com.android.internal.app.procstats.ProcessStats.STATE_PERSISTENT;
43 import static com.android.internal.app.procstats.ProcessStats.STATE_RECEIVER;
44 import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE;
45 import static com.android.internal.app.procstats.ProcessStats.STATE_SERVICE_RESTARTING;
46 import static com.android.internal.app.procstats.ProcessStats.STATE_TOP;
47 
48 import android.os.UserHandle;
49 import android.service.procstats.ProcessStatsEnums;
50 import android.service.procstats.ProcessStatsStateProto;
51 import android.util.TimeUtils;
52 import android.util.proto.ProtoOutputStream;
53 
54 import java.io.PrintWriter;
55 import java.util.ArrayList;
56 
57 /**
58  * Utilities for dumping.
59  */
60 public final class DumpUtils {
61     public static final String[] STATE_NAMES;
62     public static final String[] STATE_LABELS;
63     public static final String STATE_LABEL_TOTAL;
64     public static final String STATE_LABEL_CACHED;
65     public static final String[] STATE_NAMES_CSV;
66     static final String[] STATE_TAGS;
67     static final int[] STATE_PROTO_ENUMS;
68     private static final int[] PROCESS_STATS_STATE_TO_AGGREGATED_STATE;
69 
70     // Make the mapping easy to update.
71     static {
72         STATE_NAMES = new String[STATE_COUNT];
73         STATE_NAMES[STATE_PERSISTENT]               = "Persist";
74         STATE_NAMES[STATE_TOP]                      = "Top";
75         STATE_NAMES[STATE_BOUND_FGS]                = "BFgs";
76         STATE_NAMES[STATE_BOUND_TOP]                = "BTop";
77         STATE_NAMES[STATE_FGS]                      = "Fgs";
78         STATE_NAMES[STATE_IMPORTANT_FOREGROUND]     = "ImpFg";
79         STATE_NAMES[STATE_IMPORTANT_BACKGROUND]     = "ImpBg";
80         STATE_NAMES[STATE_BACKUP]                   = "Backup";
81         STATE_NAMES[STATE_SERVICE]                  = "Service";
82         STATE_NAMES[STATE_SERVICE_RESTARTING]       = "ServRst";
83         STATE_NAMES[STATE_RECEIVER]                 = "Receivr";
84         STATE_NAMES[STATE_HEAVY_WEIGHT]             = "HeavyWt";
85         STATE_NAMES[STATE_HOME]                     = "Home";
86         STATE_NAMES[STATE_LAST_ACTIVITY]            = "LastAct";
87         STATE_NAMES[STATE_CACHED]                   = "Cached";
88         STATE_NAMES[STATE_FROZEN]                   = "Frozen";
89 
90         STATE_LABELS = new String[STATE_COUNT];
91         STATE_LABELS[STATE_PERSISTENT]              = "Persistent";
92         STATE_LABELS[STATE_TOP]                     = "       Top";
93         STATE_LABELS[STATE_BOUND_FGS]               = "   Bnd Fgs";
94         STATE_LABELS[STATE_BOUND_TOP]               = "   Bnd Top";
95         STATE_LABELS[STATE_FGS]                     = "       Fgs";
96         STATE_LABELS[STATE_IMPORTANT_FOREGROUND]    = "    Imp Fg";
97         STATE_LABELS[STATE_IMPORTANT_BACKGROUND]    = "    Imp Bg";
98         STATE_LABELS[STATE_BACKUP]                  = "    Backup";
99         STATE_LABELS[STATE_SERVICE]                 = "   Service";
100         STATE_LABELS[STATE_SERVICE_RESTARTING]      = "Service Rs";
101         STATE_LABELS[STATE_RECEIVER]                = "  Receiver";
102         STATE_LABELS[STATE_HEAVY_WEIGHT]            = " Heavy Wgt";
103         STATE_LABELS[STATE_HOME]                    = "    (Home)";
104         STATE_LABELS[STATE_LAST_ACTIVITY]           = "(Last Act)";
105         STATE_LABELS[STATE_CACHED]                  = "  (Cached)";
106         STATE_LABELS[STATE_FROZEN]                  = "    Frozen";
107         STATE_LABEL_CACHED                          = "  (Cached)";
108         STATE_LABEL_TOTAL                           = "     TOTAL";
109 
110         STATE_NAMES_CSV = new String[STATE_COUNT];
111         STATE_NAMES_CSV[STATE_PERSISTENT]               = "pers";
112         STATE_NAMES_CSV[STATE_TOP]                      = "top";
113         STATE_NAMES_CSV[STATE_BOUND_FGS]                = "bfgs";
114         STATE_NAMES_CSV[STATE_BOUND_TOP]                = "btop";
115         STATE_NAMES_CSV[STATE_FGS]                      = "fgs";
116         STATE_NAMES_CSV[STATE_IMPORTANT_FOREGROUND]     = "impfg";
117         STATE_NAMES_CSV[STATE_IMPORTANT_BACKGROUND]     = "impbg";
118         STATE_NAMES_CSV[STATE_BACKUP]                   = "backup";
119         STATE_NAMES_CSV[STATE_SERVICE]                  = "service";
120         STATE_NAMES_CSV[STATE_SERVICE_RESTARTING]       = "service-rs";
121         STATE_NAMES_CSV[STATE_RECEIVER]                 = "receiver";
122         STATE_NAMES_CSV[STATE_HEAVY_WEIGHT]             = "heavy";
123         STATE_NAMES_CSV[STATE_HOME]                     = "home";
124         STATE_NAMES_CSV[STATE_LAST_ACTIVITY]            = "lastact";
125         STATE_NAMES_CSV[STATE_CACHED]                   = "cached";
126         STATE_NAMES_CSV[STATE_FROZEN]                   = "frzn";
127 
128         STATE_TAGS = new String[STATE_COUNT];
129         STATE_TAGS[STATE_PERSISTENT]                = "p";
130         STATE_TAGS[STATE_TOP]                       = "t";
131         STATE_TAGS[STATE_BOUND_FGS]                 = "y";
132         STATE_TAGS[STATE_BOUND_TOP]                 = "z";
133         STATE_TAGS[STATE_FGS]                       = "g";
134         STATE_TAGS[STATE_IMPORTANT_FOREGROUND]      = "f";
135         STATE_TAGS[STATE_IMPORTANT_BACKGROUND]      = "b";
136         STATE_TAGS[STATE_BACKUP]                    = "u";
137         STATE_TAGS[STATE_SERVICE]                   = "s";
138         STATE_TAGS[STATE_SERVICE_RESTARTING]        = "x";
139         STATE_TAGS[STATE_RECEIVER]                  = "r";
140         STATE_TAGS[STATE_HEAVY_WEIGHT]              = "w";
141         STATE_TAGS[STATE_HOME]                      = "h";
142         STATE_TAGS[STATE_LAST_ACTIVITY]             = "l";
143         STATE_TAGS[STATE_CACHED]                    = "a";
144         STATE_TAGS[STATE_FROZEN]                    = "e";
145 
146         STATE_PROTO_ENUMS = new int[STATE_COUNT];
147         STATE_PROTO_ENUMS[STATE_PERSISTENT] = ProcessStatsEnums.PROCESS_STATE_PERSISTENT;
148         STATE_PROTO_ENUMS[STATE_TOP] = ProcessStatsEnums.PROCESS_STATE_TOP;
149         STATE_PROTO_ENUMS[STATE_BOUND_FGS] = ProcessStatsEnums.PROCESS_STATE_BOUND_FGS;
150         STATE_PROTO_ENUMS[STATE_BOUND_TOP] = ProcessStatsEnums.PROCESS_STATE_BOUND_TOP;
151         STATE_PROTO_ENUMS[STATE_FGS] = ProcessStatsEnums.PROCESS_STATE_FGS;
152         STATE_PROTO_ENUMS[STATE_IMPORTANT_FOREGROUND] =
153                 ProcessStatsEnums.PROCESS_STATE_IMPORTANT_FOREGROUND;
154         STATE_PROTO_ENUMS[STATE_IMPORTANT_BACKGROUND] =
155                 ProcessStatsEnums.PROCESS_STATE_IMPORTANT_BACKGROUND;
156         STATE_PROTO_ENUMS[STATE_BACKUP] = ProcessStatsEnums.PROCESS_STATE_BACKUP;
157         STATE_PROTO_ENUMS[STATE_SERVICE] = ProcessStatsEnums.PROCESS_STATE_SERVICE;
158         STATE_PROTO_ENUMS[STATE_SERVICE_RESTARTING] =
159                 ProcessStatsEnums.PROCESS_STATE_SERVICE_RESTARTING;
160         STATE_PROTO_ENUMS[STATE_RECEIVER] = ProcessStatsEnums.PROCESS_STATE_RECEIVER;
161         STATE_PROTO_ENUMS[STATE_HEAVY_WEIGHT] = ProcessStatsEnums.PROCESS_STATE_HEAVY_WEIGHT;
162         STATE_PROTO_ENUMS[STATE_HOME] = ProcessStatsEnums.PROCESS_STATE_HOME;
163         STATE_PROTO_ENUMS[STATE_LAST_ACTIVITY] = ProcessStatsEnums.PROCESS_STATE_LAST_ACTIVITY;
164         STATE_PROTO_ENUMS[STATE_CACHED] = ProcessStatsEnums.PROCESS_STATE_CACHED_ACTIVITY;
165         STATE_PROTO_ENUMS[STATE_FROZEN] = ProcessStatsEnums.PROCESS_STATE_FROZEN;
166 
167         // Remap states, as defined by ProcessStats.java, to a reduced subset of states for data
168         // aggregation / size reduction purposes.
169         PROCESS_STATS_STATE_TO_AGGREGATED_STATE = new int[STATE_COUNT];
170         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_PERSISTENT] =
171                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_PERSISTENT;
172         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_TOP] =
173                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_TOP;
174         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_BOUND_FGS] =
175                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BOUND_TOP_OR_FGS;
176         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_BOUND_TOP] =
177                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BOUND_TOP_OR_FGS;
178         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_FGS] =
179                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_FGS;
180         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_IMPORTANT_FOREGROUND] =
181                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_IMPORTANT_FOREGROUND;
182         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_IMPORTANT_BACKGROUND] =
183                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BACKGROUND;
184         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_BACKUP] =
185                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BACKGROUND;
186         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_SERVICE] =
187                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BACKGROUND;
188         // "Restarting" is not a real state, so this shouldn't exist.
189         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_SERVICE_RESTARTING] =
190                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_UNKNOWN;
191         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_RECEIVER] =
192                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_RECEIVER;
193         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_HEAVY_WEIGHT] =
194                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_BACKGROUND;
195         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_HOME] =
196                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_CACHED;
197         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_LAST_ACTIVITY] =
198                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_CACHED;
199         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_CACHED] =
200                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_CACHED;
201         PROCESS_STATS_STATE_TO_AGGREGATED_STATE[STATE_FROZEN] =
202                 ProcessStatsEnums.AGGREGATED_PROCESS_STATE_CACHED;
203     }
204 
205     public static final String[] ADJ_SCREEN_NAMES_CSV = new String[] {
206             "off", "on"
207     };
208 
209     public static final String[] ADJ_MEM_NAMES_CSV = new String[] {
210             "norm", "mod",  "low", "crit"
211     };
212 
213     // State enum is defined in frameworks/base/core/proto/android/service/procstats.proto
214     // Update states must sync enum definition as well, the ordering must not be changed.
215     static final String[] ADJ_SCREEN_TAGS = new String[] {
216             "0", "1"
217     };
218 
219     static final int[] ADJ_SCREEN_PROTO_ENUMS = new int[] {
220             ProcessStatsEnums.SCREEN_STATE_OFF,
221             ProcessStatsEnums.SCREEN_STATE_ON
222     };
223 
224     static final String[] ADJ_MEM_TAGS = new String[] {
225             "n", "m",  "l", "c"
226     };
227 
228     static final int[] ADJ_MEM_PROTO_ENUMS = new int[] {
229             ProcessStatsEnums.MEMORY_STATE_NORMAL,
230             ProcessStatsEnums.MEMORY_STATE_MODERATE,
231             ProcessStatsEnums.MEMORY_STATE_LOW,
232             ProcessStatsEnums.MEMORY_STATE_CRITICAL
233     };
234 
235     static final String CSV_SEP = "\t";
236 
237     /**
238      * No instantiate
239      */
DumpUtils()240     private DumpUtils() {
241     }
242 
printScreenLabel(PrintWriter pw, int offset)243     public static void printScreenLabel(PrintWriter pw, int offset) {
244         switch (offset) {
245             case ADJ_NOTHING:
246                 pw.print("     ");
247                 break;
248             case ADJ_SCREEN_OFF:
249                 pw.print("SOff/");
250                 break;
251             case ADJ_SCREEN_ON:
252                 pw.print(" SOn/");
253                 break;
254             default:
255                 pw.print("????/");
256                 break;
257         }
258     }
259 
printScreenLabelCsv(PrintWriter pw, int offset)260     public static void printScreenLabelCsv(PrintWriter pw, int offset) {
261         switch (offset) {
262             case ADJ_NOTHING:
263                 break;
264             case ADJ_SCREEN_OFF:
265                 pw.print(ADJ_SCREEN_NAMES_CSV[0]);
266                 break;
267             case ADJ_SCREEN_ON:
268                 pw.print(ADJ_SCREEN_NAMES_CSV[1]);
269                 break;
270             default:
271                 pw.print("???");
272                 break;
273         }
274     }
275 
printMemLabel(PrintWriter pw, int offset, char sep)276     public static void printMemLabel(PrintWriter pw, int offset, char sep) {
277         switch (offset) {
278             case ADJ_NOTHING:
279                 pw.print("    ");
280                 if (sep != 0) pw.print(' ');
281                 break;
282             case ADJ_MEM_FACTOR_NORMAL:
283                 pw.print("Norm");
284                 if (sep != 0) pw.print(sep);
285                 break;
286             case ADJ_MEM_FACTOR_MODERATE:
287                 pw.print(" Mod");
288                 if (sep != 0) pw.print(sep);
289                 break;
290             case ADJ_MEM_FACTOR_LOW:
291                 pw.print(" Low");
292                 if (sep != 0) pw.print(sep);
293                 break;
294             case ADJ_MEM_FACTOR_CRITICAL:
295                 pw.print("Crit");
296                 if (sep != 0) pw.print(sep);
297                 break;
298             default:
299                 pw.print("????");
300                 if (sep != 0) pw.print(sep);
301                 break;
302         }
303     }
304 
printMemLabelCsv(PrintWriter pw, int offset)305     public static void printMemLabelCsv(PrintWriter pw, int offset) {
306         if (offset >= ADJ_MEM_FACTOR_NORMAL) {
307             if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
308                 pw.print(ADJ_MEM_NAMES_CSV[offset]);
309             } else {
310                 pw.print("???");
311             }
312         }
313     }
314 
printPercent(PrintWriter pw, double fraction)315     public static void printPercent(PrintWriter pw, double fraction) {
316         fraction *= 100;
317         if (fraction < 1) {
318             pw.print(String.format("%.2f", fraction));
319         } else if (fraction < 10) {
320             pw.print(String.format("%.1f", fraction));
321         } else {
322             pw.print(String.format("%.0f", fraction));
323         }
324         pw.print("%");
325     }
326 
printProcStateTag(PrintWriter pw, int state)327     public static void printProcStateTag(PrintWriter pw, int state) {
328         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD*STATE_COUNT);
329         state = printArrayEntry(pw, ADJ_MEM_TAGS,  state, STATE_COUNT);
330         printArrayEntry(pw, STATE_TAGS,  state, 1);
331     }
332 
printProcStateTagProto(ProtoOutputStream proto, long screenId, long memId, long stateId, int state)333     public static void printProcStateTagProto(ProtoOutputStream proto, long screenId, long memId,
334             long stateId, int state) {
335         state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
336                 state, ADJ_SCREEN_MOD * STATE_COUNT);
337         state = printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
338         printProto(proto, stateId, STATE_PROTO_ENUMS, state, 1);
339     }
340 
printAdjTag(PrintWriter pw, int state)341     public static void printAdjTag(PrintWriter pw, int state) {
342         state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD);
343         printArrayEntry(pw, ADJ_MEM_TAGS, state, 1);
344     }
345 
printProcStateAdjTagProto(ProtoOutputStream proto, long screenId, long memId, int state)346     public static void printProcStateAdjTagProto(ProtoOutputStream proto, long screenId, long memId,
347             int state) {
348         state = printProto(proto, screenId, ADJ_SCREEN_PROTO_ENUMS,
349                 state, ADJ_SCREEN_MOD * STATE_COUNT);
350         printProto(proto, memId, ADJ_MEM_PROTO_ENUMS, state, STATE_COUNT);
351     }
352 
printProcStateDurationProto(ProtoOutputStream proto, long fieldId, int procState, long duration)353     public static void printProcStateDurationProto(ProtoOutputStream proto, long fieldId,
354             int procState, long duration) {
355         final long stateToken = proto.start(fieldId);
356         DumpUtils.printProto(proto, ProcessStatsStateProto.PROCESS_STATE,
357                 DumpUtils.STATE_PROTO_ENUMS, procState, 1);
358         proto.write(ProcessStatsStateProto.DURATION_MS, duration);
359         proto.end(stateToken);
360     }
361 
printProcStateTagAndValue(PrintWriter pw, int state, long value)362     public static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
363         pw.print(',');
364         printProcStateTag(pw, state);
365         pw.print(':');
366         pw.print(value);
367     }
368 
printAdjTagAndValue(PrintWriter pw, int state, long value)369     public static void printAdjTagAndValue(PrintWriter pw, int state, long value) {
370         pw.print(',');
371         printAdjTag(pw, state);
372         pw.print(':');
373         pw.print(value);
374     }
375 
dumpSingleTime(PrintWriter pw, String prefix, long[] durations, int curState, long curStartTime, long now)376     public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
377             int curState, long curStartTime, long now) {
378         long totalTime = 0;
379         int printedScreen = -1;
380         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
381             int printedMem = -1;
382             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
383                 int state = imem+iscreen;
384                 long time = durations[state];
385                 String running = "";
386                 if (curState == state) {
387                     time += now - curStartTime;
388                     if (pw != null) {
389                         running = " (running)";
390                     }
391                 }
392                 if (time != 0) {
393                     if (pw != null) {
394                         pw.print(prefix);
395                         printScreenLabel(pw, printedScreen != iscreen
396                                 ? iscreen : STATE_NOTHING);
397                         printedScreen = iscreen;
398                         printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING, (char)0);
399                         printedMem = imem;
400                         pw.print(": ");
401                         TimeUtils.formatDuration(time, pw); pw.println(running);
402                     }
403                     totalTime += time;
404                 }
405             }
406         }
407         if (totalTime != 0 && pw != null) {
408             pw.print(prefix);
409             pw.print("    TOTAL: ");
410             TimeUtils.formatDuration(totalTime, pw);
411             pw.println();
412         }
413         return totalTime;
414     }
415 
dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations, int curState, long curStartTime, long now)416     public static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,
417             int curState, long curStartTime, long now) {
418         for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
419             for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
420                 int state = imem+iscreen;
421                 long time = durations[state];
422                 if (curState == state) {
423                     time += now - curStartTime;
424                 }
425                 if (time != 0) {
426                     printAdjTagAndValue(pw, state, time);
427                 }
428             }
429         }
430     }
431 
dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates, int[] memStates, int[] procStates)432     private static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
433             int[] memStates, int[] procStates) {
434         final int NS = screenStates != null ? screenStates.length : 1;
435         final int NM = memStates != null ? memStates.length : 1;
436         final int NP = procStates != null ? procStates.length : 1;
437         for (int is=0; is<NS; is++) {
438             for (int im=0; im<NM; im++) {
439                 for (int ip=0; ip<NP; ip++) {
440                     pw.print(sep);
441                     boolean printed = false;
442                     if (screenStates != null && screenStates.length > 1) {
443                         printScreenLabelCsv(pw, screenStates[is]);
444                         printed = true;
445                     }
446                     if (memStates != null && memStates.length > 1) {
447                         if (printed) {
448                             pw.print("-");
449                         }
450                         printMemLabelCsv(pw, memStates[im]);
451                         printed = true;
452                     }
453                     if (procStates != null && procStates.length > 1) {
454                         if (printed) {
455                             pw.print("-");
456                         }
457                         pw.print(STATE_NAMES_CSV[procStates[ip]]);
458                     }
459                 }
460             }
461         }
462     }
463 
dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header, ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates, long now, long totalTime)464     public static void dumpProcessSummaryLocked(PrintWriter pw, String prefix, String header,
465             ArrayList<ProcessState> procs, int[] screenStates, int[] memStates, int[] procStates,
466             long now, long totalTime) {
467         for (int i=procs.size()-1; i>=0; i--) {
468             final ProcessState proc = procs.get(i);
469             proc.dumpSummary(pw, prefix, header, screenStates, memStates, procStates, now,
470                     totalTime);
471         }
472     }
473 
dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs, boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, boolean sepProcStates, int[] procStates, long now)474     public static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
475             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
476             boolean sepProcStates, int[] procStates, long now) {
477         pw.print("process");
478         pw.print(CSV_SEP);
479         pw.print("uid");
480         pw.print(CSV_SEP);
481         pw.print("vers");
482         dumpStateHeadersCsv(pw, CSV_SEP, sepScreenStates ? screenStates : null,
483                 sepMemStates ? memStates : null,
484                 sepProcStates ? procStates : null);
485         pw.println();
486         for (int i=procs.size()-1; i>=0; i--) {
487             ProcessState proc = procs.get(i);
488             pw.print(proc.getName());
489             pw.print(CSV_SEP);
490             UserHandle.formatUid(pw, proc.getUid());
491             pw.print(CSV_SEP);
492             pw.print(proc.getVersion());
493             proc.dumpCsv(pw, sepScreenStates, screenStates, sepMemStates,
494                     memStates, sepProcStates, procStates, now);
495             pw.println();
496         }
497     }
498 
printArrayEntry(PrintWriter pw, String[] array, int value, int mod)499     public static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
500         int index = value/mod;
501         if (index >= 0 && index < array.length) {
502             pw.print(array[index]);
503         } else {
504             pw.print('?');
505         }
506         return value - index*mod;
507     }
508 
printProto(ProtoOutputStream proto, long fieldId, int[] enums, int value, int mod)509     public static int printProto(ProtoOutputStream proto, long fieldId,
510             int[] enums, int value, int mod) {
511         int index = value/mod;
512         if (index >= 0 && index < enums.length) {
513             proto.write(fieldId, enums[index]);
514         } // else enum default is always zero in proto3
515         return value - index*mod;
516     }
517 
collapseString(String pkgName, String itemName)518     public static String collapseString(String pkgName, String itemName) {
519         if (itemName.startsWith(pkgName)) {
520             final int ITEMLEN = itemName.length();
521             final int PKGLEN = pkgName.length();
522             if (ITEMLEN == PKGLEN) {
523                 return "";
524             } else if (ITEMLEN >= PKGLEN) {
525                 if (itemName.charAt(PKGLEN) == '.') {
526                     return itemName.substring(PKGLEN);
527                 }
528             }
529         }
530         return itemName;
531     }
532 
533     /**
534      * Aggregate process states to reduce size of statistics logs.
535      *
536      * <p>Involves unpacking the three parts of state (process state / device memory state /
537      * screen state), manipulating the elements, then re-packing the new values into a single
538      * int. This integer is guaranteed to be unique for any given combination of state elements.
539      *
540      * @param curState current state as used in mCurState in {@class ProcessState} ie. a value
541      *                 combined from the process's state, the device's memory pressure state, and
542      *                 the device's screen on/off state.
543      * @return an integer representing the combination of screen state and process state, where
544      *         process state has been aggregated.
545      */
aggregateCurrentProcessState(int curState)546     public static int aggregateCurrentProcessState(int curState) {
547         int screenStateIndex = curState / (ADJ_SCREEN_MOD * STATE_COUNT);
548         // extract process state from the compound state variable (discarding memory state)
549         int procStateIndex = curState % STATE_COUNT;
550 
551         // Remap process state per array above.
552         try {
553             procStateIndex = PROCESS_STATS_STATE_TO_AGGREGATED_STATE[procStateIndex];
554         } catch (IndexOutOfBoundsException e) {
555             procStateIndex = ProcessStatsEnums.AGGREGATED_PROCESS_STATE_UNKNOWN;
556         }
557 
558         // Pack screen & process state using bit shifting
559         return (procStateIndex << 0xf) | screenStateIndex;
560     }
561 
562     /** Print aggregated tags generated via {@code #aggregateCurrentProcessState}. */
printAggregatedProcStateTagProto(ProtoOutputStream proto, long screenId, long stateId, int state)563     public static void printAggregatedProcStateTagProto(ProtoOutputStream proto, long screenId,
564             long stateId, int state) {
565         // screen state is in lowest 0xf bits, process state is in next 0xf bits up
566 
567         try {
568             proto.write(stateId, state >> 0xf);
569         } catch (IndexOutOfBoundsException e) {
570             proto.write(stateId, ProcessStatsEnums.PROCESS_STATE_UNKNOWN);
571         }
572 
573         try {
574             proto.write(screenId, ADJ_SCREEN_PROTO_ENUMS[state & 0xf]);
575         } catch (IndexOutOfBoundsException e) {
576             proto.write(screenId, ProcessStatsEnums.SCREEN_STATE_UNKNOWN);
577         }
578     }
579 }
580