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