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