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