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