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 static android.os.PowerManager.WAKE_REASON_BIOMETRIC; 20 import static android.os.PowerManager.WAKE_REASON_GESTURE; 21 import static android.os.PowerManager.WAKE_REASON_LIFT; 22 import static android.os.PowerManager.WAKE_REASON_PLUGGED_IN; 23 import static android.os.PowerManager.WAKE_REASON_TAP; 24 25 import android.annotation.IntDef; 26 import android.os.PowerManager; 27 import android.util.TimeUtils; 28 29 import androidx.annotation.NonNull; 30 31 import com.android.keyguard.KeyguardUpdateMonitor; 32 import com.android.keyguard.KeyguardUpdateMonitorCallback; 33 import com.android.systemui.Dumpable; 34 import com.android.systemui.dagger.SysUISingleton; 35 import com.android.systemui.dump.DumpManager; 36 import com.android.systemui.statusbar.policy.DevicePostureController; 37 38 import com.google.errorprone.annotations.CompileTimeConstant; 39 40 import java.io.PrintWriter; 41 import java.lang.annotation.Retention; 42 import java.lang.annotation.RetentionPolicy; 43 44 import javax.inject.Inject; 45 46 /** 47 * Logs doze events for debugging and triaging purposes. Logs are dumped in bugreports or on demand: 48 * adb shell dumpsys activity service com.android.systemui/.SystemUIService \ 49 * dependency DumpController DozeLog,DozeStats 50 */ 51 @SysUISingleton 52 public class DozeLog implements Dumpable { 53 private final DozeLogger mLogger; 54 55 private boolean mPulsing; 56 private long mSince; 57 private SummaryStats mPickupPulseNearVibrationStats; 58 private SummaryStats mPickupPulseNotNearVibrationStats; 59 private SummaryStats mNotificationPulseStats; 60 private SummaryStats mScreenOnPulsingStats; 61 private SummaryStats mScreenOnNotPulsingStats; 62 private SummaryStats mEmergencyCallStats; 63 private SummaryStats[][] mProxStats; // [reason][near/far] 64 65 @Inject DozeLog( KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager, DozeLogger logger)66 public DozeLog( 67 KeyguardUpdateMonitor keyguardUpdateMonitor, 68 DumpManager dumpManager, 69 DozeLogger logger) { 70 mLogger = logger; 71 mSince = System.currentTimeMillis(); 72 mPickupPulseNearVibrationStats = new SummaryStats(); 73 mPickupPulseNotNearVibrationStats = new SummaryStats(); 74 mNotificationPulseStats = new SummaryStats(); 75 mScreenOnPulsingStats = new SummaryStats(); 76 mScreenOnNotPulsingStats = new SummaryStats(); 77 mEmergencyCallStats = new SummaryStats(); 78 mProxStats = new SummaryStats[TOTAL_REASONS][2]; 79 for (int i = 0; i < TOTAL_REASONS; i++) { 80 mProxStats[i][0] = new SummaryStats(); 81 mProxStats[i][1] = new SummaryStats(); 82 } 83 84 if (keyguardUpdateMonitor != null) { 85 keyguardUpdateMonitor.registerCallback(mKeyguardCallback); 86 } 87 88 dumpManager.registerDumpable("DumpStats", this); 89 } 90 91 /** 92 * Log debug message to LogBuffer. 93 */ d(@ompileTimeConstant String msg)94 public void d(@CompileTimeConstant String msg) { 95 mLogger.log(msg); 96 } 97 98 /** 99 * Appends pickup wakeup event to the logs 100 */ tracePickupWakeUp(boolean withinVibrationThreshold)101 public void tracePickupWakeUp(boolean withinVibrationThreshold) { 102 mLogger.logPickupWakeup(withinVibrationThreshold); 103 (withinVibrationThreshold ? mPickupPulseNearVibrationStats 104 : mPickupPulseNotNearVibrationStats).append(); 105 } 106 traceSetIgnoreTouchWhilePulsing(boolean ignoreTouch)107 public void traceSetIgnoreTouchWhilePulsing(boolean ignoreTouch) { 108 mLogger.logSetIgnoreTouchWhilePulsing(ignoreTouch); 109 } 110 111 /** 112 * Appends pulse started event to the logs. 113 * @param reason why the pulse started 114 */ tracePulseStart(@eason int reason)115 public void tracePulseStart(@Reason int reason) { 116 mLogger.logPulseStart(reason); 117 mPulsing = true; 118 } 119 120 /** 121 * Appends pulse finished event to the logs 122 */ tracePulseFinish()123 public void tracePulseFinish() { 124 mLogger.logPulseFinish(); 125 mPulsing = false; 126 } 127 128 /** 129 * Appends pulse event to the logs 130 */ traceNotificationPulse()131 public void traceNotificationPulse() { 132 mLogger.logNotificationPulse(); 133 mNotificationPulseStats.append(); 134 } 135 136 /** 137 * Appends dozing event to the logs. Logs current dozing state when entering/exiting AOD. 138 * @param dozing true if dozing, else false 139 */ traceDozing(boolean dozing)140 public void traceDozing(boolean dozing) { 141 mLogger.logDozing(dozing); 142 mPulsing = false; 143 } 144 145 /** 146 * Appends dozing event to the logs when dozing has changed in AOD. 147 * @param dozing true if we're now dozing, else false 148 */ traceDozingChanged(boolean dozing)149 public void traceDozingChanged(boolean dozing) { 150 mLogger.logDozingChanged(dozing); 151 } 152 153 /** 154 * Appends fling event to the logs 155 */ traceFling(boolean expand, boolean aboveThreshold, boolean screenOnFromTouch)156 public void traceFling(boolean expand, boolean aboveThreshold, 157 boolean screenOnFromTouch) { 158 mLogger.logFling(expand, aboveThreshold, screenOnFromTouch); 159 } 160 161 /** 162 * Appends emergency call event to the logs 163 */ traceEmergencyCall()164 public void traceEmergencyCall() { 165 mLogger.logEmergencyCall(); 166 mEmergencyCallStats.append(); 167 } 168 169 /** 170 * Appends keyguard bouncer changed event to the logs 171 * @param showing true if the keyguard bouncer is showing, else false 172 */ traceKeyguardBouncerChanged(boolean showing)173 public void traceKeyguardBouncerChanged(boolean showing) { 174 mLogger.logKeyguardBouncerChanged(showing); 175 } 176 177 /** 178 * Appends screen-on event to the logs 179 */ traceScreenOn()180 public void traceScreenOn() { 181 mLogger.logScreenOn(mPulsing); 182 (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append(); 183 mPulsing = false; 184 } 185 186 /** 187 * Appends screen-off event to the logs 188 * @param why reason the screen is off 189 */ traceScreenOff(int why)190 public void traceScreenOff(int why) { 191 mLogger.logScreenOff(why); 192 } 193 194 /** 195 * Appends missed tick event to the logs 196 * @param delay of the missed tick 197 */ traceMissedTick(String delay)198 public void traceMissedTick(String delay) { 199 mLogger.logMissedTick(delay); 200 } 201 202 /** 203 * Appends time tick scheduled event to the logs 204 * @param when time tick scheduled at 205 * @param triggerAt time tick trigger at 206 */ traceTimeTickScheduled(long when, long triggerAt)207 public void traceTimeTickScheduled(long when, long triggerAt) { 208 mLogger.logTimeTickScheduled(when, triggerAt); 209 } 210 211 /** 212 * Logs cancelation requests for time ticks 213 * @param isPending is an unschedule request pending? 214 * @param isTimeTickScheduled is a time tick request scheduled 215 */ tracePendingUnscheduleTimeTick(boolean isPending, boolean isTimeTickScheduled)216 public void tracePendingUnscheduleTimeTick(boolean isPending, boolean isTimeTickScheduled) { 217 mLogger.logPendingUnscheduleTimeTick(isPending, isTimeTickScheduled); 218 } 219 220 /** 221 * Appends keyguard visibility change event to the logs 222 * @param showing whether the keyguard is now showing 223 */ traceKeyguard(boolean showing)224 public void traceKeyguard(boolean showing) { 225 mLogger.logKeyguardVisibilityChange(showing); 226 if (!showing) mPulsing = false; 227 } 228 229 /** 230 * Appends doze state changed event to the logs 231 * @param state new DozeMachine state 232 */ traceState(DozeMachine.State state)233 public void traceState(DozeMachine.State state) { 234 mLogger.logDozeStateChanged(state); 235 } 236 237 /** 238 * Appends doze state changed sent to all DozeMachine parts event to the logs 239 * @param state new DozeMachine state 240 */ traceDozeStateSendComplete(DozeMachine.State state)241 public void traceDozeStateSendComplete(DozeMachine.State state) { 242 mLogger.logStateChangedSent(state); 243 } 244 245 /** 246 * Appends display state delayed by UDFPS event to the logs 247 * @param delayedDisplayState the display screen state that was delayed 248 */ traceDisplayStateDelayedByUdfps(int delayedDisplayState)249 public void traceDisplayStateDelayedByUdfps(int delayedDisplayState) { 250 mLogger.logDisplayStateDelayedByUdfps(delayedDisplayState); 251 } 252 253 /** 254 * Appends display state changed event to the logs 255 * @param displayState new DozeMachine state 256 */ traceDisplayState(int displayState)257 public void traceDisplayState(int displayState) { 258 mLogger.logDisplayStateChanged(displayState); 259 } 260 261 /** 262 * Appends wake-display event to the logs. 263 * @param wake if we're waking up or sleeping. 264 */ traceWakeDisplay(boolean wake, @Reason int reason)265 public void traceWakeDisplay(boolean wake, @Reason int reason) { 266 mLogger.logWakeDisplay(wake, reason); 267 } 268 269 /** 270 * Appends proximity result event to the logs 271 * @param near true if near, else false 272 * @param reason why proximity result was triggered 273 */ traceProximityResult(boolean near, long millis, @Reason int reason)274 public void traceProximityResult(boolean near, long millis, @Reason int reason) { 275 mLogger.logProximityResult(near, millis, reason); 276 mProxStats[reason][near ? 0 : 1].append(); 277 } 278 279 @Override dump(@onNull PrintWriter pw, @NonNull String[] args)280 public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { 281 synchronized (DozeLog.class) { 282 pw.print(" Doze summary stats (for "); 283 TimeUtils.formatDuration(System.currentTimeMillis() - mSince, pw); 284 pw.println("):"); 285 mPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)"); 286 mPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)"); 287 mNotificationPulseStats.dump(pw, "Notification pulse"); 288 mScreenOnPulsingStats.dump(pw, "Screen on (pulsing)"); 289 mScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)"); 290 mEmergencyCallStats.dump(pw, "Emergency call"); 291 for (int i = 0; i < TOTAL_REASONS; i++) { 292 final String reason = reasonToString(i); 293 mProxStats[i][0].dump(pw, "Proximity near (" + reason + ")"); 294 mProxStats[i][1].dump(pw, "Proximity far (" + reason + ")"); 295 } 296 } 297 } 298 299 /** 300 * Appends doze updates due to a posture change. 301 */ tracePostureChanged( @evicePostureController.DevicePostureInt int posture, String partUpdated )302 public void tracePostureChanged( 303 @DevicePostureController.DevicePostureInt int posture, 304 String partUpdated 305 ) { 306 mLogger.logPostureChanged(posture, partUpdated); 307 } 308 309 /** 310 * Appends pulse dropped event to logs 311 */ tracePulseDropped(String from, DozeMachine.State state)312 public void tracePulseDropped(String from, DozeMachine.State state) { 313 mLogger.logPulseDropped(from, state); 314 } 315 316 /** 317 * Appends sensor event dropped event to logs 318 */ traceSensorEventDropped(@eason int pulseReason, String reason)319 public void traceSensorEventDropped(@Reason int pulseReason, String reason) { 320 mLogger.logSensorEventDropped(pulseReason, reason); 321 } 322 323 /** 324 * Appends pulsing event to logs. 325 */ tracePulseEvent(String pulseEvent, boolean dozing, int pulseReason)326 public void tracePulseEvent(String pulseEvent, boolean dozing, int pulseReason) { 327 mLogger.logPulseEvent(pulseEvent, dozing, DozeLog.reasonToString(pulseReason)); 328 } 329 330 /** 331 * Appends pulse dropped event to logs 332 * @param reason why the pulse was dropped 333 */ tracePulseDropped(String reason)334 public void tracePulseDropped(String reason) { 335 mLogger.logPulseDropped(reason); 336 } 337 338 /** 339 * Appends pulse touch displayed by prox sensor event to logs 340 * @param disabled 341 */ tracePulseTouchDisabledByProx(boolean disabled)342 public void tracePulseTouchDisabledByProx(boolean disabled) { 343 mLogger.logPulseTouchDisabledByProx(disabled); 344 } 345 346 /** 347 * Appends sensor triggered event to logs 348 * @param reason why the sensor was triggered 349 */ traceSensor(@eason int reason)350 public void traceSensor(@Reason int reason) { 351 mLogger.logSensorTriggered(reason); 352 } 353 354 /** 355 * Appends the doze state that was suppressed to the doze event log 356 * @param suppressedState The {@link DozeMachine.State} that was suppressed 357 * @param reason what suppressed always on 358 */ traceAlwaysOnSuppressed(DozeMachine.State suppressedState, String reason)359 public void traceAlwaysOnSuppressed(DozeMachine.State suppressedState, String reason) { 360 mLogger.logAlwaysOnSuppressed(suppressedState, reason); 361 } 362 363 /** 364 * Appends reason why doze immediately ended. 365 */ traceImmediatelyEndDoze(String reason)366 public void traceImmediatelyEndDoze(String reason) { 367 mLogger.logImmediatelyEndDoze(reason); 368 } 369 370 /** 371 * Logs the car mode started event. 372 */ traceCarModeStarted()373 public void traceCarModeStarted() { 374 mLogger.logCarModeStarted(); 375 } 376 377 /** 378 * Logs the car mode ended event. 379 */ traceCarModeEnded()380 public void traceCarModeEnded() { 381 mLogger.logCarModeEnded(); 382 } 383 384 /** 385 * Appends power save changes that may cause a new doze state 386 * @param powerSaveActive true if power saving is active 387 * @param nextState the state that we'll transition to 388 */ tracePowerSaveChanged(boolean powerSaveActive, DozeMachine.State nextState)389 public void tracePowerSaveChanged(boolean powerSaveActive, DozeMachine.State nextState) { 390 mLogger.logPowerSaveChanged(powerSaveActive, nextState); 391 } 392 393 /** 394 * Appends an event on AOD suppression change 395 * @param suppressed true if AOD is being suppressed 396 * @param nextState the state that we'll transition to 397 */ traceAlwaysOnSuppressedChange(boolean suppressed, DozeMachine.State nextState)398 public void traceAlwaysOnSuppressedChange(boolean suppressed, DozeMachine.State nextState) { 399 mLogger.logAlwaysOnSuppressedChange(suppressed, nextState); 400 } 401 402 /** 403 * Appends new AOD screen brightness to logs 404 * @param brightness display brightness setting 405 */ traceDozeScreenBrightness(int brightness)406 public void traceDozeScreenBrightness(int brightness) { 407 mLogger.logDozeScreenBrightness(brightness); 408 } 409 410 /** 411 * Appends new AOD dimming scrim opacity to logs 412 * @param scrimOpacity 413 */ traceSetAodDimmingScrim(float scrimOpacity)414 public void traceSetAodDimmingScrim(float scrimOpacity) { 415 mLogger.logSetAodDimmingScrim((long) scrimOpacity); 416 } 417 418 /** 419 * Appends sensor attempted to register and whether it was a successful registration. 420 */ traceSensorRegisterAttempt(String sensorName, boolean successfulRegistration)421 public void traceSensorRegisterAttempt(String sensorName, boolean successfulRegistration) { 422 mLogger.logSensorRegisterAttempt(sensorName, successfulRegistration); 423 } 424 425 /** 426 * Appends sensor attempted to unregister and whether it was successfully unregistered. 427 */ traceSensorUnregisterAttempt(String sensorInfo, boolean successfullyUnregistered)428 public void traceSensorUnregisterAttempt(String sensorInfo, boolean successfullyUnregistered) { 429 mLogger.logSensorUnregisterAttempt(sensorInfo, successfullyUnregistered); 430 } 431 432 /** 433 * Appends sensor attempted to unregister and whether it was successfully unregistered 434 * with a reason the sensor is being unregistered. 435 */ traceSensorUnregisterAttempt(String sensorInfo, boolean successfullyUnregistered, String reason)436 public void traceSensorUnregisterAttempt(String sensorInfo, boolean successfullyUnregistered, 437 String reason) { 438 mLogger.logSensorUnregisterAttempt(sensorInfo, successfullyUnregistered, reason); 439 } 440 441 /** 442 * Appends the event of skipping a sensor registration since it's already registered. 443 */ traceSkipRegisterSensor(String sensorInfo)444 public void traceSkipRegisterSensor(String sensorInfo) { 445 mLogger.logSkipSensorRegistration(sensorInfo); 446 } 447 448 /** 449 * Appends a plugin sensor was registered or unregistered event. 450 */ tracePluginSensorUpdate(boolean registered)451 public void tracePluginSensorUpdate(boolean registered) { 452 if (registered) { 453 mLogger.log("register plugin sensor"); 454 } else { 455 mLogger.log("unregister plugin sensor"); 456 } 457 } 458 459 private class SummaryStats { 460 private int mCount; 461 append()462 public void append() { 463 mCount++; 464 } 465 dump(PrintWriter pw, String type)466 public void dump(PrintWriter pw, String type) { 467 if (mCount == 0) return; 468 pw.print(" "); 469 pw.print(type); 470 pw.print(": n="); 471 pw.print(mCount); 472 pw.print(" ("); 473 final double perHr = (double) mCount / (System.currentTimeMillis() - mSince) 474 * 1000 * 60 * 60; 475 pw.print(perHr); 476 pw.print("/hr)"); 477 pw.println(); 478 } 479 } 480 481 private final KeyguardUpdateMonitorCallback mKeyguardCallback = 482 new KeyguardUpdateMonitorCallback() { 483 @Override 484 public void onEmergencyCallAction() { 485 traceEmergencyCall(); 486 } 487 488 @Override 489 public void onKeyguardBouncerFullyShowingChanged(boolean fullyShowing) { 490 traceKeyguardBouncerChanged(fullyShowing); 491 } 492 493 @Override 494 public void onStartedWakingUp() { 495 traceScreenOn(); 496 } 497 498 @Override 499 public void onFinishedGoingToSleep(int why) { 500 traceScreenOff(why); 501 } 502 503 @Override 504 public void onKeyguardVisibilityChanged(boolean visible) { 505 traceKeyguard(visible); 506 } 507 }; 508 509 /** 510 * Converts the reason (integer) to a user-readable string 511 */ reasonToString(@eason int pulseReason)512 public static String reasonToString(@Reason int pulseReason) { 513 switch (pulseReason) { 514 case PULSE_REASON_INTENT: return "intent"; 515 case PULSE_REASON_NOTIFICATION: return "notification"; 516 case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion"; 517 case REASON_SENSOR_PICKUP: return "pickup"; 518 case REASON_SENSOR_DOUBLE_TAP: return "doubletap"; 519 case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress"; 520 case PULSE_REASON_DOCKING: return "docking"; 521 case PULSE_REASON_SENSOR_WAKE_REACH: return "reach-wakelockscreen"; 522 case REASON_SENSOR_WAKE_UP_PRESENCE: return "presence-wakeup"; 523 case REASON_SENSOR_TAP: return "tap"; 524 case REASON_SENSOR_UDFPS_LONG_PRESS: return "udfps"; 525 case REASON_SENSOR_QUICK_PICKUP: return "quickPickup"; 526 case PULSE_REASON_FINGERPRINT_ACTIVATED: return "fingerprint-triggered"; 527 default: throw new IllegalArgumentException("invalid reason: " + pulseReason); 528 } 529 } 530 531 /** 532 * Converts {@link Reason} to {@link PowerManager.WakeReason}. 533 */ getPowerManagerWakeReason(@eason int wakeReason)534 public static @PowerManager.WakeReason int getPowerManagerWakeReason(@Reason int wakeReason) { 535 switch (wakeReason) { 536 case REASON_SENSOR_DOUBLE_TAP: 537 case REASON_SENSOR_TAP: 538 return WAKE_REASON_TAP; 539 case REASON_SENSOR_PICKUP: 540 return WAKE_REASON_LIFT; 541 case REASON_SENSOR_UDFPS_LONG_PRESS: 542 return WAKE_REASON_BIOMETRIC; 543 case PULSE_REASON_DOCKING: 544 return WAKE_REASON_PLUGGED_IN; 545 default: 546 return WAKE_REASON_GESTURE; 547 } 548 } 549 550 @Retention(RetentionPolicy.SOURCE) 551 @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION, 552 PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP, 553 PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP_PRESENCE, 554 PULSE_REASON_SENSOR_WAKE_REACH, REASON_SENSOR_TAP, 555 REASON_SENSOR_UDFPS_LONG_PRESS, REASON_SENSOR_QUICK_PICKUP, 556 PULSE_REASON_FINGERPRINT_ACTIVATED 557 }) 558 public @interface Reason {} 559 public static final int PULSE_REASON_NONE = -1; 560 public static final int PULSE_REASON_INTENT = 0; 561 public static final int PULSE_REASON_NOTIFICATION = 1; 562 public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; 563 public static final int REASON_SENSOR_PICKUP = 3; 564 public static final int REASON_SENSOR_DOUBLE_TAP = 4; 565 public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5; 566 public static final int PULSE_REASON_DOCKING = 6; 567 public static final int REASON_SENSOR_WAKE_UP_PRESENCE = 7; 568 public static final int PULSE_REASON_SENSOR_WAKE_REACH = 8; 569 public static final int REASON_SENSOR_TAP = 9; 570 public static final int REASON_SENSOR_UDFPS_LONG_PRESS = 10; 571 public static final int REASON_SENSOR_QUICK_PICKUP = 11; 572 public static final int PULSE_REASON_FINGERPRINT_ACTIVATED = 12; 573 574 public static final int TOTAL_REASONS = 13; 575 } 576