1 /* 2 * Copyright (C) 2016 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.server.am; 18 19 import android.os.SystemClock; 20 import android.util.ArrayMap; 21 import android.util.TimeUtils; 22 23 import dalvik.annotation.optimization.NeverCompile; 24 25 import java.io.PrintWriter; 26 import java.util.ArrayList; 27 import java.util.Collections; 28 import java.util.Comparator; 29 30 public final class BroadcastStats { 31 final long mStartRealtime; 32 final long mStartUptime; 33 long mEndRealtime; 34 long mEndUptime; 35 final ArrayMap<String, ActionEntry> mActions = new ArrayMap<>(); 36 37 static final Comparator<ActionEntry> ACTIONS_COMPARATOR = new Comparator<ActionEntry>() { 38 @Override public int compare(ActionEntry o1, ActionEntry o2) { 39 if (o1.mTotalDispatchTime < o2.mTotalDispatchTime) { 40 return -1; 41 } 42 if (o1.mTotalDispatchTime > o2.mTotalDispatchTime) { 43 return 1; 44 } 45 return 0; 46 } 47 }; 48 49 static final class ActionEntry { 50 final String mAction; 51 final ArrayMap<String, PackageEntry> mPackages = new ArrayMap<>(); 52 final ArrayMap<String, ViolationEntry> mBackgroundCheckViolations = new ArrayMap<>(); 53 int mReceiveCount; 54 int mSkipCount; 55 long mTotalDispatchTime; 56 long mMaxDispatchTime; 57 ActionEntry(String action)58 ActionEntry(String action) { 59 mAction = action; 60 } 61 } 62 63 static final class PackageEntry { 64 int mSendCount; 65 } 66 67 static final class ViolationEntry { 68 int mCount; 69 } 70 BroadcastStats()71 public BroadcastStats() { 72 mStartRealtime = SystemClock.elapsedRealtime(); 73 mStartUptime = SystemClock.uptimeMillis(); 74 } 75 addBroadcast(String action, String srcPackage, int receiveCount, int skipCount, long dispatchTime)76 public void addBroadcast(String action, String srcPackage, int receiveCount, 77 int skipCount, long dispatchTime) { 78 ActionEntry ae = mActions.get(action); 79 if (ae == null) { 80 ae = new ActionEntry(action); 81 mActions.put(action, ae); 82 } 83 ae.mReceiveCount += receiveCount; 84 ae.mSkipCount += skipCount; 85 ae.mTotalDispatchTime += dispatchTime; 86 if (ae.mMaxDispatchTime < dispatchTime) { 87 ae.mMaxDispatchTime = dispatchTime; 88 } 89 PackageEntry pe = ae.mPackages.get(srcPackage); 90 if (pe == null) { 91 pe = new PackageEntry(); 92 ae.mPackages.put(srcPackage, pe); 93 } 94 pe.mSendCount++; 95 } 96 addBackgroundCheckViolation(String action, String targetPackage)97 public void addBackgroundCheckViolation(String action, String targetPackage) { 98 ActionEntry ae = mActions.get(action); 99 if (ae == null) { 100 ae = new ActionEntry(action); 101 mActions.put(action, ae); 102 } 103 ViolationEntry ve = ae.mBackgroundCheckViolations.get(targetPackage); 104 if (ve == null) { 105 ve = new ViolationEntry(); 106 ae.mBackgroundCheckViolations.put(targetPackage, ve); 107 } 108 ve.mCount++; 109 } 110 111 @NeverCompile dumpStats(PrintWriter pw, String prefix, String dumpPackage)112 public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) { 113 boolean printedSomething = false; 114 ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size()); 115 for (int i=mActions.size()-1; i>=0; i--) { 116 actions.add(mActions.valueAt(i)); 117 } 118 Collections.sort(actions, ACTIONS_COMPARATOR); 119 for (int i=actions.size()-1; i>=0; i--) { 120 ActionEntry ae = actions.get(i); 121 if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) { 122 continue; 123 } 124 printedSomething = true; 125 pw.print(prefix); 126 pw.print(ae.mAction); 127 pw.println(":"); 128 pw.print(prefix); 129 pw.print(" Number received: "); 130 pw.print(ae.mReceiveCount); 131 pw.print(", skipped: "); 132 pw.println(ae.mSkipCount); 133 pw.print(prefix); 134 pw.print(" Total dispatch time: "); 135 TimeUtils.formatDuration(ae.mTotalDispatchTime, pw); 136 pw.print(", max: "); 137 TimeUtils.formatDuration(ae.mMaxDispatchTime, pw); 138 pw.println(); 139 for (int j=ae.mPackages.size()-1; j>=0; j--) { 140 pw.print(prefix); 141 pw.print(" Package "); 142 pw.print(ae.mPackages.keyAt(j)); 143 pw.print(": "); 144 PackageEntry pe = ae.mPackages.valueAt(j); 145 pw.print(pe.mSendCount); 146 pw.println(" times"); 147 } 148 for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) { 149 pw.print(prefix); 150 pw.print(" Bg Check Violation "); 151 pw.print(ae.mBackgroundCheckViolations.keyAt(j)); 152 pw.print(": "); 153 ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j); 154 pw.print(ve.mCount); 155 pw.println(" times"); 156 } 157 } 158 return printedSomething; 159 } 160 161 @NeverCompile dumpCheckinStats(PrintWriter pw, String dumpPackage)162 public void dumpCheckinStats(PrintWriter pw, String dumpPackage) { 163 pw.print("broadcast-stats,1,"); 164 pw.print(mStartRealtime); 165 pw.print(","); 166 pw.print(mEndRealtime == 0 ? SystemClock.elapsedRealtime() : mEndRealtime); 167 pw.print(","); 168 pw.println((mEndUptime == 0 ? SystemClock.uptimeMillis() : mEndUptime) - mStartUptime); 169 for (int i=mActions.size()-1; i>=0; i--) { 170 ActionEntry ae = mActions.valueAt(i); 171 if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) { 172 continue; 173 } 174 pw.print("a,"); 175 pw.print(mActions.keyAt(i)); 176 pw.print(","); 177 pw.print(ae.mReceiveCount); 178 pw.print(","); 179 pw.print(ae.mSkipCount); 180 pw.print(","); 181 pw.print(ae.mTotalDispatchTime); 182 pw.print(","); 183 pw.print(ae.mMaxDispatchTime); 184 pw.println(); 185 for (int j=ae.mPackages.size()-1; j>=0; j--) { 186 pw.print("p,"); 187 pw.print(ae.mPackages.keyAt(j)); 188 PackageEntry pe = ae.mPackages.valueAt(j); 189 pw.print(","); 190 pw.print(pe.mSendCount); 191 pw.println(); 192 } 193 for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) { 194 pw.print("v,"); 195 pw.print(ae.mBackgroundCheckViolations.keyAt(j)); 196 ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j); 197 pw.print(","); 198 pw.print(ve.mCount); 199 pw.println(); 200 } 201 } 202 } 203 } 204