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.annotation.IntDef; 20 import android.util.TimeUtils; 21 22 import androidx.annotation.NonNull; 23 24 import com.android.keyguard.KeyguardUpdateMonitor; 25 import com.android.keyguard.KeyguardUpdateMonitorCallback; 26 import com.android.systemui.Dumpable; 27 import com.android.systemui.dump.DumpManager; 28 29 import java.io.FileDescriptor; 30 import java.io.PrintWriter; 31 import java.lang.annotation.Retention; 32 import java.lang.annotation.RetentionPolicy; 33 34 import javax.inject.Inject; 35 import javax.inject.Singleton; 36 37 /** 38 * Logs doze events for debugging and triaging purposes. Logs are dumped in bugreports or on demand: 39 * adb shell dumpsys activity service com.android.systemui/.SystemUIService \ 40 * dependency DumpController DozeLog,DozeStats 41 */ 42 @Singleton 43 public class DozeLog implements Dumpable { 44 private final DozeLogger mLogger; 45 46 private boolean mPulsing; 47 private long mSince; 48 private SummaryStats mPickupPulseNearVibrationStats; 49 private SummaryStats mPickupPulseNotNearVibrationStats; 50 private SummaryStats mNotificationPulseStats; 51 private SummaryStats mScreenOnPulsingStats; 52 private SummaryStats mScreenOnNotPulsingStats; 53 private SummaryStats mEmergencyCallStats; 54 private SummaryStats[][] mProxStats; // [reason][near/far] 55 56 @Inject DozeLog( KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager, DozeLogger logger)57 public DozeLog( 58 KeyguardUpdateMonitor keyguardUpdateMonitor, 59 DumpManager dumpManager, 60 DozeLogger logger) { 61 mLogger = logger; 62 mSince = System.currentTimeMillis(); 63 mPickupPulseNearVibrationStats = new SummaryStats(); 64 mPickupPulseNotNearVibrationStats = new SummaryStats(); 65 mNotificationPulseStats = new SummaryStats(); 66 mScreenOnPulsingStats = new SummaryStats(); 67 mScreenOnNotPulsingStats = new SummaryStats(); 68 mEmergencyCallStats = new SummaryStats(); 69 mProxStats = new SummaryStats[TOTAL_REASONS][2]; 70 for (int i = 0; i < TOTAL_REASONS; i++) { 71 mProxStats[i][0] = new SummaryStats(); 72 mProxStats[i][1] = new SummaryStats(); 73 } 74 75 if (keyguardUpdateMonitor != null) { 76 keyguardUpdateMonitor.registerCallback(mKeyguardCallback); 77 } 78 79 dumpManager.registerDumpable("DumpStats", this); 80 } 81 82 /** 83 * Appends pickup wakeup event to the logs 84 */ tracePickupWakeUp(boolean withinVibrationThreshold)85 public void tracePickupWakeUp(boolean withinVibrationThreshold) { 86 mLogger.logPickupWakeup(withinVibrationThreshold); 87 (withinVibrationThreshold ? mPickupPulseNearVibrationStats 88 : mPickupPulseNotNearVibrationStats).append(); 89 } 90 91 /** 92 * Appends pulse started event to the logs. 93 * @param reason why the pulse started 94 */ tracePulseStart(@eason int reason)95 public void tracePulseStart(@Reason int reason) { 96 mLogger.logPulseStart(reason); 97 mPulsing = true; 98 } 99 100 /** 101 * Appends pulse finished event to the logs 102 */ tracePulseFinish()103 public void tracePulseFinish() { 104 mLogger.logPulseFinish(); 105 mPulsing = false; 106 } 107 108 /** 109 * Appends pulse event to the logs 110 */ traceNotificationPulse()111 public void traceNotificationPulse() { 112 mLogger.logNotificationPulse(); 113 mNotificationPulseStats.append(); 114 } 115 116 /** 117 * Appends dozing event to the logs 118 * @param dozing true if dozing, else false 119 */ traceDozing(boolean dozing)120 public void traceDozing(boolean dozing) { 121 mLogger.logDozing(dozing); 122 mPulsing = false; 123 } 124 125 /** 126 * Appends fling event to the logs 127 */ traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded, boolean screenOnFromTouch)128 public void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded, 129 boolean screenOnFromTouch) { 130 mLogger.logFling(expand, aboveThreshold, thresholdNeeded, screenOnFromTouch); 131 } 132 133 /** 134 * Appends emergency call event to the logs 135 */ traceEmergencyCall()136 public void traceEmergencyCall() { 137 mLogger.logEmergencyCall(); 138 mEmergencyCallStats.append(); 139 } 140 141 /** 142 * Appends keyguard bouncer changed event to the logs 143 * @param showing true if the keyguard bouncer is showing, else false 144 */ traceKeyguardBouncerChanged(boolean showing)145 public void traceKeyguardBouncerChanged(boolean showing) { 146 mLogger.logKeyguardBouncerChanged(showing); 147 } 148 149 /** 150 * Appends screen-on event to the logs 151 */ traceScreenOn()152 public void traceScreenOn() { 153 mLogger.logScreenOn(mPulsing); 154 (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append(); 155 mPulsing = false; 156 } 157 158 /** 159 * Appends screen-off event to the logs 160 * @param why reason the screen is off 161 */ traceScreenOff(int why)162 public void traceScreenOff(int why) { 163 mLogger.logScreenOff(why); 164 } 165 166 /** 167 * Appends missed tick event to the logs 168 * @param delay of the missed tick 169 */ traceMissedTick(String delay)170 public void traceMissedTick(String delay) { 171 mLogger.logMissedTick(delay); 172 } 173 174 /** 175 * Appends time tick scheduled event to the logs 176 * @param when time tick scheduled at 177 * @param triggerAt time tick trigger at 178 */ traceTimeTickScheduled(long when, long triggerAt)179 public void traceTimeTickScheduled(long when, long triggerAt) { 180 mLogger.logTimeTickScheduled(when, triggerAt); 181 } 182 183 /** 184 * Appends keyguard visibility change event to the logs 185 * @param showing whether the keyguard is now showing 186 */ traceKeyguard(boolean showing)187 public void traceKeyguard(boolean showing) { 188 mLogger.logKeyguardVisibilityChange(showing); 189 if (!showing) mPulsing = false; 190 } 191 192 /** 193 * Appends doze state changed event to the logs 194 * @param state new DozeMachine state 195 */ traceState(DozeMachine.State state)196 public void traceState(DozeMachine.State state) { 197 mLogger.logDozeStateChanged(state); 198 } 199 200 /** 201 * Appends wake-display event to the logs. 202 * @param wake if we're waking up or sleeping. 203 */ traceWakeDisplay(boolean wake)204 public void traceWakeDisplay(boolean wake) { 205 mLogger.logWakeDisplay(wake); 206 } 207 208 /** 209 * Appends proximity result event to the logs 210 * @param near true if near, else false 211 * @param reason why proximity result was triggered 212 */ traceProximityResult(boolean near, long millis, @Reason int reason)213 public void traceProximityResult(boolean near, long millis, @Reason int reason) { 214 mLogger.logProximityResult(near, millis, reason); 215 mProxStats[reason][near ? 0 : 1].append(); 216 } 217 218 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)219 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { 220 synchronized (DozeLog.class) { 221 pw.print(" Doze summary stats (for "); 222 TimeUtils.formatDuration(System.currentTimeMillis() - mSince, pw); 223 pw.println("):"); 224 mPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)"); 225 mPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)"); 226 mNotificationPulseStats.dump(pw, "Notification pulse"); 227 mScreenOnPulsingStats.dump(pw, "Screen on (pulsing)"); 228 mScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)"); 229 mEmergencyCallStats.dump(pw, "Emergency call"); 230 for (int i = 0; i < TOTAL_REASONS; i++) { 231 final String reason = reasonToString(i); 232 mProxStats[i][0].dump(pw, "Proximity near (" + reason + ")"); 233 mProxStats[i][1].dump(pw, "Proximity far (" + reason + ")"); 234 } 235 } 236 } 237 238 /** 239 * Appends pulse dropped event to logs 240 */ tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked)241 public void tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked) { 242 mLogger.logPulseDropped(pulsePending, state, blocked); 243 } 244 245 /** 246 * Appends pulse dropped event to logs 247 * @param reason why the pulse was dropped 248 */ tracePulseDropped(String reason)249 public void tracePulseDropped(String reason) { 250 mLogger.logPulseDropped(reason); 251 } 252 253 /** 254 * Appends pulse touch displayed by prox sensor event to logs 255 * @param disabled 256 */ tracePulseTouchDisabledByProx(boolean disabled)257 public void tracePulseTouchDisabledByProx(boolean disabled) { 258 mLogger.logPulseTouchDisabledByProx(disabled); 259 } 260 261 /** 262 * Appends sensor triggered event to logs 263 * @param reason why the sensor was triggered 264 */ traceSensor(@eason int reason)265 public void traceSensor(@Reason int reason) { 266 mLogger.logSensorTriggered(reason); 267 } 268 269 /** 270 * Appends doze suppressed event to the logs 271 * @param suppressedState The {@link DozeMachine.State} that was suppressed 272 */ traceDozeSuppressed(DozeMachine.State suppressedState)273 public void traceDozeSuppressed(DozeMachine.State suppressedState) { 274 mLogger.logDozeSuppressed(suppressedState); 275 } 276 277 private class SummaryStats { 278 private int mCount; 279 append()280 public void append() { 281 mCount++; 282 } 283 dump(PrintWriter pw, String type)284 public void dump(PrintWriter pw, String type) { 285 if (mCount == 0) return; 286 pw.print(" "); 287 pw.print(type); 288 pw.print(": n="); 289 pw.print(mCount); 290 pw.print(" ("); 291 final double perHr = (double) mCount / (System.currentTimeMillis() - mSince) 292 * 1000 * 60 * 60; 293 pw.print(perHr); 294 pw.print("/hr)"); 295 pw.println(); 296 } 297 } 298 299 private final KeyguardUpdateMonitorCallback mKeyguardCallback = 300 new KeyguardUpdateMonitorCallback() { 301 @Override 302 public void onEmergencyCallAction() { 303 traceEmergencyCall(); 304 } 305 306 @Override 307 public void onKeyguardBouncerChanged(boolean bouncer) { 308 traceKeyguardBouncerChanged(bouncer); 309 } 310 311 @Override 312 public void onStartedWakingUp() { 313 traceScreenOn(); 314 } 315 316 @Override 317 public void onFinishedGoingToSleep(int why) { 318 traceScreenOff(why); 319 } 320 321 @Override 322 public void onKeyguardVisibilityChanged(boolean showing) { 323 traceKeyguard(showing); 324 } 325 }; 326 327 /** 328 * Converts the reason (integer) to a user-readable string 329 */ reasonToString(@eason int pulseReason)330 public static String reasonToString(@Reason int pulseReason) { 331 switch (pulseReason) { 332 case PULSE_REASON_INTENT: return "intent"; 333 case PULSE_REASON_NOTIFICATION: return "notification"; 334 case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion"; 335 case REASON_SENSOR_PICKUP: return "pickup"; 336 case REASON_SENSOR_DOUBLE_TAP: return "doubletap"; 337 case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress"; 338 case PULSE_REASON_DOCKING: return "docking"; 339 case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen"; 340 case REASON_SENSOR_WAKE_UP: return "wakeup"; 341 case REASON_SENSOR_TAP: return "tap"; 342 default: throw new IllegalArgumentException("invalid reason: " + pulseReason); 343 } 344 } 345 346 @Retention(RetentionPolicy.SOURCE) 347 @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION, 348 PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP, 349 PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP, 350 PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP}) 351 public @interface Reason {} 352 public static final int PULSE_REASON_NONE = -1; 353 public static final int PULSE_REASON_INTENT = 0; 354 public static final int PULSE_REASON_NOTIFICATION = 1; 355 public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; 356 public static final int REASON_SENSOR_PICKUP = 3; 357 public static final int REASON_SENSOR_DOUBLE_TAP = 4; 358 public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5; 359 public static final int PULSE_REASON_DOCKING = 6; 360 public static final int REASON_SENSOR_WAKE_UP = 7; 361 public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8; 362 public static final int REASON_SENSOR_TAP = 9; 363 364 public static final int TOTAL_REASONS = 10; 365 } 366