OSDN Git Service

7139d59c6eefea976540e41c72bc565646b60f3d
[android-x86/frameworks-base.git] / packages / SystemUI / src / com / android / systemui / doze / DozeLog.java
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     static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
37
38     private static final int PULSE_REASONS = 5;
39
40     public static final int PULSE_REASON_INTENT = 0;
41     public static final int PULSE_REASON_NOTIFICATION = 1;
42     public static final int PULSE_REASON_SENSOR_SIGMOTION = 2;
43     public static final int PULSE_REASON_SENSOR_PICKUP = 3;
44     public static final int PULSE_REASON_SENSOR_DOUBLE_TAP = 4;
45
46     private static boolean sRegisterKeyguardCallback = true;
47
48     private static long[] sTimes;
49     private static String[] sMessages;
50     private static int sPosition;
51     private static int sCount;
52     private static boolean sPulsing;
53
54     private static long sSince;
55     private static SummaryStats sPickupPulseNearVibrationStats;
56     private static SummaryStats sPickupPulseNotNearVibrationStats;
57     private static SummaryStats sNotificationPulseStats;
58     private static SummaryStats sScreenOnPulsingStats;
59     private static SummaryStats sScreenOnNotPulsingStats;
60     private static SummaryStats sEmergencyCallStats;
61     private static SummaryStats[][] sProxStats; // [reason][near/far]
62
63     public static void tracePickupPulse(Context context, boolean withinVibrationThreshold) {
64         if (!ENABLED) return;
65         init(context);
66         log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
67         (withinVibrationThreshold ? sPickupPulseNearVibrationStats
68                 : sPickupPulseNotNearVibrationStats).append();
69     }
70
71     public static void tracePulseStart(int reason) {
72         if (!ENABLED) return;
73         sPulsing = true;
74         log("pulseStart reason=" + pulseReasonToString(reason));
75     }
76
77     public static void tracePulseFinish() {
78         if (!ENABLED) return;
79         sPulsing = false;
80         log("pulseFinish");
81     }
82
83     public static void traceNotificationPulse(Context context) {
84         if (!ENABLED) return;
85         init(context);
86         log("notificationPulse");
87         sNotificationPulseStats.append();
88     }
89
90     private static void init(Context context) {
91         synchronized (DozeLog.class) {
92             if (sMessages == null) {
93                 sTimes = new long[SIZE];
94                 sMessages = new String[SIZE];
95                 sSince = System.currentTimeMillis();
96                 sPickupPulseNearVibrationStats = new SummaryStats();
97                 sPickupPulseNotNearVibrationStats = new SummaryStats();
98                 sNotificationPulseStats = new SummaryStats();
99                 sScreenOnPulsingStats = new SummaryStats();
100                 sScreenOnNotPulsingStats = new SummaryStats();
101                 sEmergencyCallStats = new SummaryStats();
102                 sProxStats = new SummaryStats[PULSE_REASONS][2];
103                 for (int i = 0; i < PULSE_REASONS; i++) {
104                     sProxStats[i][0] = new SummaryStats();
105                     sProxStats[i][1] = new SummaryStats();
106                 }
107                 log("init");
108                 if (sRegisterKeyguardCallback) {
109                     KeyguardUpdateMonitor.getInstance(context).registerCallback(sKeyguardCallback);
110                 }
111             }
112         }
113     }
114
115     public static void traceDozing(Context context, boolean dozing) {
116         if (!ENABLED) return;
117         sPulsing = false;
118         init(context);
119         log("dozing " + dozing);
120     }
121
122     public static void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded,
123             boolean screenOnFromTouch) {
124         if (!ENABLED) return;
125         log("fling expand=" + expand + " aboveThreshold=" + aboveThreshold + " thresholdNeeded="
126                 + thresholdNeeded + " screenOnFromTouch=" + screenOnFromTouch);
127     }
128
129     public static void traceEmergencyCall() {
130         if (!ENABLED) return;
131         log("emergencyCall");
132         sEmergencyCallStats.append();
133     }
134
135     public static void traceKeyguardBouncerChanged(boolean showing) {
136         if (!ENABLED) return;
137         log("bouncer " + showing);
138     }
139
140     public static void traceScreenOn() {
141         if (!ENABLED) return;
142         log("screenOn pulsing=" + sPulsing);
143         (sPulsing ? sScreenOnPulsingStats : sScreenOnNotPulsingStats).append();
144         sPulsing = false;
145     }
146
147     public static void traceScreenOff(int why) {
148         if (!ENABLED) return;
149         log("screenOff why=" + why);
150     }
151
152     public static void traceMissedTick(String delay) {
153         if (!ENABLED) return;
154         log("missedTick by=" + delay);
155     }
156
157     public static void traceKeyguard(boolean showing) {
158         if (!ENABLED) return;
159         log("keyguard " + showing);
160         if (!showing) {
161             sPulsing = false;
162         }
163     }
164
165     public static void traceProximityResult(Context context, boolean near, long millis,
166             int pulseReason) {
167         if (!ENABLED) return;
168         init(context);
169         log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
170                 + " millis=" + millis);
171         sProxStats[pulseReason][near ? 0 : 1].append();
172     }
173
174     public static String pulseReasonToString(int pulseReason) {
175         switch (pulseReason) {
176             case PULSE_REASON_INTENT: return "intent";
177             case PULSE_REASON_NOTIFICATION: return "notification";
178             case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion";
179             case PULSE_REASON_SENSOR_PICKUP: return "pickup";
180             case PULSE_REASON_SENSOR_DOUBLE_TAP: return "doubletap";
181             default: throw new IllegalArgumentException("bad reason: " + pulseReason);
182         }
183     }
184
185     public static void dump(PrintWriter pw) {
186         synchronized (DozeLog.class) {
187             if (sMessages == null) return;
188             pw.println("  Doze log:");
189             final int start = (sPosition - sCount + SIZE) % SIZE;
190             for (int i = 0; i < sCount; i++) {
191                 final int j = (start + i) % SIZE;
192                 pw.print("    ");
193                 pw.print(FORMAT.format(new Date(sTimes[j])));
194                 pw.print(' ');
195                 pw.println(sMessages[j]);
196             }
197             pw.print("  Doze summary stats (for ");
198             TimeUtils.formatDuration(System.currentTimeMillis() - sSince, pw);
199             pw.println("):");
200             sPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)");
201             sPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)");
202             sNotificationPulseStats.dump(pw, "Notification pulse");
203             sScreenOnPulsingStats.dump(pw, "Screen on (pulsing)");
204             sScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)");
205             sEmergencyCallStats.dump(pw, "Emergency call");
206             for (int i = 0; i < PULSE_REASONS; i++) {
207                 final String reason = pulseReasonToString(i);
208                 sProxStats[i][0].dump(pw, "Proximity near (" + reason + ")");
209                 sProxStats[i][1].dump(pw, "Proximity far (" + reason + ")");
210             }
211         }
212     }
213
214     private static void log(String msg) {
215         synchronized (DozeLog.class) {
216             if (sMessages == null) return;
217             sTimes[sPosition] = System.currentTimeMillis();
218             sMessages[sPosition] = msg;
219             sPosition = (sPosition + 1) % SIZE;
220             sCount = Math.min(sCount + 1, SIZE);
221         }
222         if (DEBUG) Log.d(TAG, msg);
223     }
224
225     public static void tracePulseDropped(Context context, boolean pulsePending,
226             DozeMachine.State state, boolean blocked) {
227         if (!ENABLED) return;
228         init(context);
229         log("pulseDropped pulsePending=" + pulsePending + " state="
230                 + state + " blocked=" + blocked);
231     }
232
233     public static void tracePulseCanceledByProx(Context context) {
234         if (!ENABLED) return;
235         init(context);
236         log("pulseCanceledByProx");
237     }
238
239     public static void setRegisterKeyguardCallback(boolean registerKeyguardCallback) {
240         if (!ENABLED) return;
241         synchronized (DozeLog.class) {
242             if (sRegisterKeyguardCallback != registerKeyguardCallback && sMessages != null) {
243                 throw new IllegalStateException("Cannot change setRegisterKeyguardCallback "
244                         + "after init()");
245             }
246             sRegisterKeyguardCallback = registerKeyguardCallback;
247         }
248     }
249
250     private static class SummaryStats {
251         private int mCount;
252
253         public void append() {
254             mCount++;
255         }
256
257         public void dump(PrintWriter pw, String type) {
258             if (mCount == 0) return;
259             pw.print("    ");
260             pw.print(type);
261             pw.print(": n=");
262             pw.print(mCount);
263             pw.print(" (");
264             final double perHr = (double) mCount / (System.currentTimeMillis() - sSince)
265                     * 1000 * 60 * 60;
266             pw.print(perHr);
267             pw.print("/hr)");
268             pw.println();
269         }
270     }
271
272     private static final KeyguardUpdateMonitorCallback sKeyguardCallback =
273             new KeyguardUpdateMonitorCallback() {
274         @Override
275         public void onEmergencyCallAction() {
276             traceEmergencyCall();
277         }
278
279         @Override
280         public void onKeyguardBouncerChanged(boolean bouncer) {
281             traceKeyguardBouncerChanged(bouncer);
282         }
283
284         @Override
285         public void onStartedWakingUp() {
286             traceScreenOn();
287         }
288
289         @Override
290         public void onFinishedGoingToSleep(int why) {
291             traceScreenOff(why);
292         }
293
294         @Override
295         public void onKeyguardVisibilityChanged(boolean showing) {
296             traceKeyguard(showing);
297         }
298     };
299 }