Home | History | Annotate | Download | only in doze
      1 /*
      2  * Copyright (C) 2014 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.systemui.doze;
     18 
     19 import android.content.Context;
     20 import android.os.Build;
     21 import android.util.Log;
     22 import android.util.TimeUtils;
     23 
     24 import com.android.keyguard.KeyguardUpdateMonitor;
     25 import com.android.keyguard.KeyguardUpdateMonitorCallback;
     26 
     27 import java.io.PrintWriter;
     28 import java.text.SimpleDateFormat;
     29 import java.util.Date;
     30 
     31 public class DozeLog {
     32     private static final String TAG = "DozeLog";
     33     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     34     private static final boolean ENABLED = true;
     35     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
     36     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
     37 
     38     private static long[] sTimes;
     39     private static String[] sMessages;
     40     private static int sPosition;
     41     private static int sCount;
     42     private static boolean sPulsing;
     43 
     44     private static long sSince;
     45     private static SummaryStats sPickupPulseNearVibrationStats;
     46     private static SummaryStats sPickupPulseNotNearVibrationStats;
     47     private static SummaryStats sNotificationPulseStats;
     48     private static SummaryStats sScreenOnPulsingStats;
     49     private static SummaryStats sScreenOnNotPulsingStats;
     50     private static SummaryStats sEmergencyCallStats;
     51     private static SummaryStats sProxNearStats;
     52     private static SummaryStats sProxFarStats;
     53 
     54     public static void tracePickupPulse(boolean withinVibrationThreshold) {
     55         if (!ENABLED) return;
     56         log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
     57         (withinVibrationThreshold ? sPickupPulseNearVibrationStats
     58                 : sPickupPulseNotNearVibrationStats).append();
     59     }
     60 
     61     public static void tracePulseStart() {
     62         if (!ENABLED) return;
     63         sPulsing = true;
     64         log("pulseStart");
     65     }
     66 
     67     public static void tracePulseFinish() {
     68         if (!ENABLED) return;
     69         sPulsing = false;
     70         log("pulseFinish");
     71     }
     72 
     73     public static void traceNotificationPulse(long instance) {
     74         if (!ENABLED) return;
     75         log("notificationPulse instance=" + instance);
     76         sNotificationPulseStats.append();
     77     }
     78 
     79     public static void traceDozing(Context context, boolean dozing) {
     80         if (!ENABLED) return;
     81         sPulsing = false;
     82         synchronized (DozeLog.class) {
     83             if (dozing && sMessages == null) {
     84                 sTimes = new long[SIZE];
     85                 sMessages = new String[SIZE];
     86                 sSince = System.currentTimeMillis();
     87                 sPickupPulseNearVibrationStats = new SummaryStats();
     88                 sPickupPulseNotNearVibrationStats = new SummaryStats();
     89                 sNotificationPulseStats = new SummaryStats();
     90                 sScreenOnPulsingStats = new SummaryStats();
     91                 sScreenOnNotPulsingStats = new SummaryStats();
     92                 sEmergencyCallStats = new SummaryStats();
     93                 sProxNearStats = new SummaryStats();
     94                 sProxFarStats = new SummaryStats();
     95                 log("init");
     96                 KeyguardUpdateMonitor.getInstance(context).registerCallback(sKeyguardCallback);
     97             }
     98         }
     99         log("dozing " + dozing);
    100     }
    101 
    102     public static void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded,
    103             boolean screenOnFromTouch) {
    104         if (!ENABLED) return;
    105         log("fling expand=" + expand + " aboveThreshold=" + aboveThreshold + " thresholdNeeded="
    106                 + thresholdNeeded + " screenOnFromTouch=" + screenOnFromTouch);
    107     }
    108 
    109     public static void traceEmergencyCall() {
    110         if (!ENABLED) return;
    111         log("emergencyCall");
    112         sEmergencyCallStats.append();
    113     }
    114 
    115     public static void traceKeyguardBouncerChanged(boolean showing) {
    116         if (!ENABLED) return;
    117         log("bouncer " + showing);
    118     }
    119 
    120     public static void traceScreenOn() {
    121         if (!ENABLED) return;
    122         log("screenOn pulsing=" + sPulsing);
    123         (sPulsing ? sScreenOnPulsingStats : sScreenOnNotPulsingStats).append();
    124         sPulsing = false;
    125     }
    126 
    127     public static void traceScreenOff(int why) {
    128         if (!ENABLED) return;
    129         log("screenOff why=" + why);
    130     }
    131 
    132     public static void traceKeyguard(boolean showing) {
    133         if (!ENABLED) return;
    134         log("keyguard " + showing);
    135         if (!showing) {
    136             sPulsing = false;
    137         }
    138     }
    139 
    140     public static void traceProximityResult(boolean near, long millis) {
    141         if (!ENABLED) return;
    142         log("proximityResult near=" + near + " millis=" + millis);
    143         (near ? sProxNearStats : sProxFarStats).append();
    144     }
    145 
    146     public static void dump(PrintWriter pw) {
    147         synchronized (DozeLog.class) {
    148             if (sMessages == null) return;
    149             pw.println("  Doze log:");
    150             final int start = (sPosition - sCount + SIZE) % SIZE;
    151             for (int i = 0; i < sCount; i++) {
    152                 final int j = (start + i) % SIZE;
    153                 pw.print("    ");
    154                 pw.print(FORMAT.format(new Date(sTimes[j])));
    155                 pw.print(' ');
    156                 pw.println(sMessages[j]);
    157             }
    158             pw.print("  Doze summary stats (for ");
    159             TimeUtils.formatDuration(System.currentTimeMillis() - sSince, pw);
    160             pw.println("):");
    161             sPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)");
    162             sPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)");
    163             sNotificationPulseStats.dump(pw, "Notification pulse");
    164             sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
    165             sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
    166             sEmergencyCallStats.dump(pw, "Emergency call");
    167             sProxNearStats.dump(pw, "Proximity (near)");
    168             sProxFarStats.dump(pw, "Proximity (far)");
    169         }
    170     }
    171 
    172     private static void log(String msg) {
    173         synchronized (DozeLog.class) {
    174             if (sMessages == null) return;
    175             sTimes[sPosition] = System.currentTimeMillis();
    176             sMessages[sPosition] = msg;
    177             sPosition = (sPosition + 1) % SIZE;
    178             sCount = Math.min(sCount + 1, SIZE);
    179         }
    180         if (DEBUG) Log.d(TAG, msg);
    181     }
    182 
    183     private static class SummaryStats {
    184         private int mCount;
    185 
    186         public void append() {
    187             mCount++;
    188         }
    189 
    190         public void dump(PrintWriter pw, String type) {
    191             pw.print("    ");
    192             pw.print(type);
    193             pw.print(": n=");
    194             pw.print(mCount);
    195             pw.print(" (");
    196             final double perHr = (double) mCount / (System.currentTimeMillis() - sSince)
    197                     * 1000 * 60 * 60;
    198             pw.print(perHr);
    199             pw.print("/hr)");
    200             pw.println();
    201         }
    202     }
    203 
    204     private static final KeyguardUpdateMonitorCallback sKeyguardCallback =
    205             new KeyguardUpdateMonitorCallback() {
    206         @Override
    207         public void onEmergencyCallAction() {
    208             traceEmergencyCall();
    209         }
    210 
    211         @Override
    212         public void onKeyguardBouncerChanged(boolean bouncer) {
    213             traceKeyguardBouncerChanged(bouncer);
    214         }
    215 
    216         @Override
    217         public void onScreenTurnedOn() {
    218             traceScreenOn();
    219         }
    220 
    221         @Override
    222         public void onScreenTurnedOff(int why) {
    223             traceScreenOff(why);
    224         }
    225 
    226         @Override
    227         public void onKeyguardVisibilityChanged(boolean showing) {
    228             traceKeyguard(showing);
    229         }
    230     };
    231 }
    232