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