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