2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.systemui.doze;
19 import android.content.Context;
20 import android.os.Build;
21 import android.util.Log;
22 import android.util.TimeUtils;
24 import com.android.keyguard.KeyguardUpdateMonitor;
25 import com.android.keyguard.KeyguardUpdateMonitorCallback;
27 import java.io.PrintWriter;
28 import java.text.SimpleDateFormat;
29 import java.util.Date;
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");
38 private static final int PULSE_REASONS = 5;
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;
46 private static boolean sRegisterKeyguardCallback = true;
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;
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]
63 public static void tracePickupPulse(Context context, boolean withinVibrationThreshold) {
66 log("pickupPulse withinVibrationThreshold=" + withinVibrationThreshold);
67 (withinVibrationThreshold ? sPickupPulseNearVibrationStats
68 : sPickupPulseNotNearVibrationStats).append();
71 public static void tracePulseStart(int reason) {
74 log("pulseStart reason=" + pulseReasonToString(reason));
77 public static void tracePulseFinish() {
83 public static void traceNotificationPulse(Context context) {
86 log("notificationPulse");
87 sNotificationPulseStats.append();
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();
108 if (sRegisterKeyguardCallback) {
109 KeyguardUpdateMonitor.getInstance(context).registerCallback(sKeyguardCallback);
115 public static void traceDozing(Context context, boolean dozing) {
116 if (!ENABLED) return;
119 log("dozing " + dozing);
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);
129 public static void traceEmergencyCall() {
130 if (!ENABLED) return;
131 log("emergencyCall");
132 sEmergencyCallStats.append();
135 public static void traceKeyguardBouncerChanged(boolean showing) {
136 if (!ENABLED) return;
137 log("bouncer " + showing);
140 public static void traceScreenOn() {
141 if (!ENABLED) return;
142 log("screenOn pulsing=" + sPulsing);
143 (sPulsing ? sScreenOnPulsingStats : sScreenOnNotPulsingStats).append();
147 public static void traceScreenOff(int why) {
148 if (!ENABLED) return;
149 log("screenOff why=" + why);
152 public static void traceMissedTick(String delay) {
153 if (!ENABLED) return;
154 log("missedTick by=" + delay);
157 public static void traceKeyguard(boolean showing) {
158 if (!ENABLED) return;
159 log("keyguard " + showing);
165 public static void traceProximityResult(Context context, boolean near, long millis,
167 if (!ENABLED) return;
169 log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
170 + " millis=" + millis);
171 sProxStats[pulseReason][near ? 0 : 1].append();
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);
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;
193 pw.print(FORMAT.format(new Date(sTimes[j])));
195 pw.println(sMessages[j]);
197 pw.print(" Doze summary stats (for ");
198 TimeUtils.formatDuration(System.currentTimeMillis() - sSince, pw);
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 + ")");
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);
222 if (DEBUG) Log.d(TAG, msg);
225 public static void tracePulseDropped(Context context, boolean pulsePending,
226 DozeMachine.State state, boolean blocked) {
227 if (!ENABLED) return;
229 log("pulseDropped pulsePending=" + pulsePending + " state="
230 + state + " blocked=" + blocked);
233 public static void tracePulseCanceledByProx(Context context) {
234 if (!ENABLED) return;
236 log("pulseCanceledByProx");
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 "
246 sRegisterKeyguardCallback = registerKeyguardCallback;
250 private static class SummaryStats {
253 public void append() {
257 public void dump(PrintWriter pw, String type) {
258 if (mCount == 0) return;
264 final double perHr = (double) mCount / (System.currentTimeMillis() - sSince)
272 private static final KeyguardUpdateMonitorCallback sKeyguardCallback =
273 new KeyguardUpdateMonitorCallback() {
275 public void onEmergencyCallAction() {
276 traceEmergencyCall();
280 public void onKeyguardBouncerChanged(boolean bouncer) {
281 traceKeyguardBouncerChanged(bouncer);
285 public void onStartedWakingUp() {
290 public void onFinishedGoingToSleep(int why) {
295 public void onKeyguardVisibilityChanged(boolean showing) {
296 traceKeyguard(showing);