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         int mReceiveCount;
     51         int mSkipCount;
     52         long mTotalDispatchTime;
     53         long mMaxDispatchTime;
     54 
     55         ActionEntry(String action) {
     56             mAction = action;
     57         }
     58     }
     59 
     60     static final class PackageEntry {
     61         int mSendCount;
     62     }
     63 
     64     public BroadcastStats() {
     65         mStartRealtime = SystemClock.elapsedRealtime();
     66         mStartUptime = SystemClock.uptimeMillis();
     67     }
     68 
     69     public void addBroadcast(String action, String srcPackage, int receiveCount,
     70             int skipCount, long dispatchTime) {
     71         ActionEntry ae = mActions.get(action);
     72         if (ae == null) {
     73             ae = new ActionEntry(action);
     74             mActions.put(action, ae);
     75         }
     76         ae.mReceiveCount += receiveCount;
     77         ae.mSkipCount += skipCount;
     78         ae.mTotalDispatchTime += dispatchTime;
     79         if (ae.mMaxDispatchTime < dispatchTime) {
     80             ae.mMaxDispatchTime = dispatchTime;
     81         }
     82         PackageEntry pe = ae.mPackages.get(srcPackage);
     83         if (pe == null) {
     84             pe = new PackageEntry();
     85             ae.mPackages.put(srcPackage, pe);
     86         }
     87         pe.mSendCount++;
     88     }
     89 
     90     public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) {
     91         boolean printedSomething = false;
     92         ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size());
     93         for (int i=mActions.size()-1; i>=0; i--) {
     94             actions.add(mActions.valueAt(i));
     95         }
     96         Collections.sort(actions, ACTIONS_COMPARATOR);
     97         for (int i=actions.size()-1; i>=0; i--) {
     98             ActionEntry ae = actions.get(i);
     99             if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
    100                 continue;
    101             }
    102             printedSomething = true;
    103             pw.print(prefix);
    104             pw.print(ae.mAction);
    105             pw.println(":");
    106             pw.print(prefix);
    107             pw.print("  Number received: ");
    108             pw.print(ae.mReceiveCount);
    109             pw.print(", skipped: ");
    110             pw.println(ae.mSkipCount);
    111             pw.print(prefix);
    112             pw.print("  Total dispatch time: ");
    113             TimeUtils.formatDuration(ae.mTotalDispatchTime, pw);
    114             pw.print(", max: ");
    115             TimeUtils.formatDuration(ae.mMaxDispatchTime, pw);
    116             pw.println();
    117             for (int j=ae.mPackages.size()-1; j>=0; j--) {
    118                 pw.print(prefix);
    119                 pw.print("  Package ");
    120                 pw.print(ae.mPackages.keyAt(j));
    121                 pw.print(": ");
    122                 PackageEntry pe = ae.mPackages.valueAt(j);
    123                 pw.print(pe.mSendCount);
    124                 pw.println(" times");
    125             }
    126         }
    127         return printedSomething;
    128     }
    129 
    130     public void dumpCheckinStats(PrintWriter pw, String dumpPackage) {
    131         pw.print("broadcast-stats,1,");
    132         pw.print(mStartRealtime);
    133         pw.print(",");
    134         pw.print(mEndRealtime == 0 ? SystemClock.elapsedRealtime() : mEndRealtime);
    135         pw.print(",");
    136         pw.println((mEndUptime == 0 ? SystemClock.uptimeMillis() : mEndUptime) - mStartUptime);
    137         for (int i=mActions.size()-1; i>=0; i--) {
    138             ActionEntry ae = mActions.valueAt(i);
    139             if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
    140                 continue;
    141             }
    142             pw.print("a,");
    143             pw.print(mActions.keyAt(i));
    144             pw.print(",");
    145             pw.print(ae.mReceiveCount);
    146             pw.print(",");
    147             pw.print(ae.mSkipCount);
    148             pw.print(",");
    149             pw.print(ae.mTotalDispatchTime);
    150             pw.print(",");
    151             pw.print(ae.mMaxDispatchTime);
    152             pw.println();
    153             for (int j=ae.mPackages.size()-1; j>=0; j--) {
    154                 pw.print("p,");
    155                 pw.print(ae.mPackages.keyAt(j));
    156                 PackageEntry pe = ae.mPackages.valueAt(j);
    157                 pw.print(",");
    158                 pw.print(pe.mSendCount);
    159                 pw.println();
    160             }
    161         }
    162     }
    163 }
    164