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.dagger.SysUISingleton; 28 import com.android.systemui.dump.DumpManager; 29 30 import java.io.FileDescriptor; 31 import java.io.PrintWriter; 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 35 import javax.inject.Inject; 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 @SysUISingleton 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 dozing event to the logs 127 * @param suppressed true if dozing is suppressed 128 */ traceDozingSuppressed(boolean suppressed)129 public void traceDozingSuppressed(boolean suppressed) { 130 mLogger.logDozingSuppressed(suppressed); 131 } 132 133 /** 134 * Appends fling event to the logs 135 */ traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded, boolean screenOnFromTouch)136 public void traceFling(boolean expand, boolean aboveThreshold, boolean thresholdNeeded, 137 boolean screenOnFromTouch) { 138 mLogger.logFling(expand, aboveThreshold, thresholdNeeded, screenOnFromTouch); 139 } 140 141 /** 142 * Appends emergency call event to the logs 143 */ traceEmergencyCall()144 public void traceEmergencyCall() { 145 mLogger.logEmergencyCall(); 146 mEmergencyCallStats.append(); 147 } 148 149 /** 150 * Appends keyguard bouncer changed event to the logs 151 * @param showing true if the keyguard bouncer is showing, else false 152 */ traceKeyguardBouncerChanged(boolean showing)153 public void traceKeyguardBouncerChanged(boolean showing) { 154 mLogger.logKeyguardBouncerChanged(showing); 155 } 156 157 /** 158 * Appends screen-on event to the logs 159 */ traceScreenOn()160 public void traceScreenOn() { 161 mLogger.logScreenOn(mPulsing); 162 (mPulsing ? mScreenOnPulsingStats : mScreenOnNotPulsingStats).append(); 163 mPulsing = false; 164 } 165 166 /** 167 * Appends screen-off event to the logs 168 * @param why reason the screen is off 169 */ traceScreenOff(int why)170 public void traceScreenOff(int why) { 171 mLogger.logScreenOff(why); 172 } 173 174 /** 175 * Appends missed tick event to the logs 176 * @param delay of the missed tick 177 */ traceMissedTick(String delay)178 public void traceMissedTick(String delay) { 179 mLogger.logMissedTick(delay); 180 } 181 182 /** 183 * Appends time tick scheduled event to the logs 184 * @param when time tick scheduled at 185 * @param triggerAt time tick trigger at 186 */ traceTimeTickScheduled(long when, long triggerAt)187 public void traceTimeTickScheduled(long when, long triggerAt) { 188 mLogger.logTimeTickScheduled(when, triggerAt); 189 } 190 191 /** 192 * Appends keyguard visibility change event to the logs 193 * @param showing whether the keyguard is now showing 194 */ traceKeyguard(boolean showing)195 public void traceKeyguard(boolean showing) { 196 mLogger.logKeyguardVisibilityChange(showing); 197 if (!showing) mPulsing = false; 198 } 199 200 /** 201 * Appends doze state changed event to the logs 202 * @param state new DozeMachine state 203 */ traceState(DozeMachine.State state)204 public void traceState(DozeMachine.State state) { 205 mLogger.logDozeStateChanged(state); 206 } 207 208 /** 209 * Appends doze state changed sent to all DozeMachine parts event to the logs 210 * @param state new DozeMachine state 211 */ traceDozeStateSendComplete(DozeMachine.State state)212 public void traceDozeStateSendComplete(DozeMachine.State state) { 213 mLogger.logStateChangedSent(state); 214 } 215 216 /** 217 * Appends display state changed event to the logs 218 * @param displayState new DozeMachine state 219 */ traceDisplayState(int displayState)220 public void traceDisplayState(int displayState) { 221 mLogger.logDisplayStateChanged(displayState); 222 } 223 224 /** 225 * Appends wake-display event to the logs. 226 * @param wake if we're waking up or sleeping. 227 */ traceWakeDisplay(boolean wake, @Reason int reason)228 public void traceWakeDisplay(boolean wake, @Reason int reason) { 229 mLogger.logWakeDisplay(wake, reason); 230 } 231 232 /** 233 * Appends proximity result event to the logs 234 * @param near true if near, else false 235 * @param reason why proximity result was triggered 236 */ traceProximityResult(boolean near, long millis, @Reason int reason)237 public void traceProximityResult(boolean near, long millis, @Reason int reason) { 238 mLogger.logProximityResult(near, millis, reason); 239 mProxStats[reason][near ? 0 : 1].append(); 240 } 241 242 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)243 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { 244 synchronized (DozeLog.class) { 245 pw.print(" Doze summary stats (for "); 246 TimeUtils.formatDuration(System.currentTimeMillis() - mSince, pw); 247 pw.println("):"); 248 mPickupPulseNearVibrationStats.dump(pw, "Pickup pulse (near vibration)"); 249 mPickupPulseNotNearVibrationStats.dump(pw, "Pickup pulse (not near vibration)"); 250 mNotificationPulseStats.dump(pw, "Notification pulse"); 251 mScreenOnPulsingStats.dump(pw, "Screen on (pulsing)"); 252 mScreenOnNotPulsingStats.dump(pw, "Screen on (not pulsing)"); 253 mEmergencyCallStats.dump(pw, "Emergency call"); 254 for (int i = 0; i < TOTAL_REASONS; i++) { 255 final String reason = reasonToString(i); 256 mProxStats[i][0].dump(pw, "Proximity near (" + reason + ")"); 257 mProxStats[i][1].dump(pw, "Proximity far (" + reason + ")"); 258 } 259 } 260 } 261 262 /** 263 * Appends pulse dropped event to logs 264 */ tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked)265 public void tracePulseDropped(boolean pulsePending, DozeMachine.State state, boolean blocked) { 266 mLogger.logPulseDropped(pulsePending, state, blocked); 267 } 268 269 /** 270 * Appends pulse dropped event to logs 271 * @param reason why the pulse was dropped 272 */ tracePulseDropped(String reason)273 public void tracePulseDropped(String reason) { 274 mLogger.logPulseDropped(reason); 275 } 276 277 /** 278 * Appends pulse touch displayed by prox sensor event to logs 279 * @param disabled 280 */ tracePulseTouchDisabledByProx(boolean disabled)281 public void tracePulseTouchDisabledByProx(boolean disabled) { 282 mLogger.logPulseTouchDisabledByProx(disabled); 283 } 284 285 /** 286 * Appends sensor triggered event to logs 287 * @param reason why the sensor was triggered 288 */ traceSensor(@eason int reason)289 public void traceSensor(@Reason int reason) { 290 mLogger.logSensorTriggered(reason); 291 } 292 293 /** 294 * Appends doze suppressed event to the logs 295 * @param suppressedState The {@link DozeMachine.State} that was suppressed 296 */ traceDozeSuppressed(DozeMachine.State suppressedState)297 public void traceDozeSuppressed(DozeMachine.State suppressedState) { 298 mLogger.logDozeSuppressed(suppressedState); 299 } 300 301 /** 302 * Appends new AOD sreen brightness to logs 303 * @param brightness display brightness setting 304 */ traceDozeScreenBrightness(int brightness)305 public void traceDozeScreenBrightness(int brightness) { 306 mLogger.logDozeScreenBrightness(brightness); 307 } 308 309 /** 310 * Appends new AOD dimming scrim opacity to logs 311 * @param scrimOpacity 312 */ traceSetAodDimmingScrim(float scrimOpacity)313 public void traceSetAodDimmingScrim(float scrimOpacity) { 314 mLogger.logSetAodDimmingScrim((long) scrimOpacity); 315 } 316 317 private class SummaryStats { 318 private int mCount; 319 append()320 public void append() { 321 mCount++; 322 } 323 dump(PrintWriter pw, String type)324 public void dump(PrintWriter pw, String type) { 325 if (mCount == 0) return; 326 pw.print(" "); 327 pw.print(type); 328 pw.print(": n="); 329 pw.print(mCount); 330 pw.print(" ("); 331 final double perHr = (double) mCount / (System.currentTimeMillis() - mSince) 332 * 1000 * 60 * 60; 333 pw.print(perHr); 334 pw.print("/hr)"); 335 pw.println(); 336 } 337 } 338 339 private final KeyguardUpdateMonitorCallback mKeyguardCallback = 340 new KeyguardUpdateMonitorCallback() { 341 @Override 342 public void onEmergencyCallAction() { 343 traceEmergencyCall(); 344 } 345 346 @Override 347 public void onKeyguardBouncerChanged(boolean bouncer) { 348 traceKeyguardBouncerChanged(bouncer); 349 } 350 351 @Override 352 public void onStartedWakingUp() { 353 traceScreenOn(); 354 } 355 356 @Override 357 public void onFinishedGoingToSleep(int why) { 358 traceScreenOff(why); 359 } 360 361 @Override 362 public void onKeyguardVisibilityChanged(boolean showing) { 363 traceKeyguard(showing); 364 } 365 }; 366 367 /** 368 * Converts the reason (integer) to a user-readable string 369 */ reasonToString(@eason int pulseReason)370 public static String reasonToString(@Reason int pulseReason) { 371 switch (pulseReason) { 372 case PULSE_REASON_INTENT: return "intent"; 373 case PULSE_REASON_NOTIFICATION: return "notification"; 374 case PULSE_REASON_SENSOR_SIGMOTION: return "sigmotion"; 375 case REASON_SENSOR_PICKUP: return "pickup"; 376 case REASON_SENSOR_DOUBLE_TAP: return "doubletap"; 377 case PULSE_REASON_SENSOR_LONG_PRESS: return "longpress"; 378 case PULSE_REASON_DOCKING: return "docking"; 379 case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "reach-wakelockscreen"; 380 case REASON_SENSOR_WAKE_UP: return "presence-wakeup"; 381 case REASON_SENSOR_TAP: return "tap"; 382 case REASON_SENSOR_UDFPS_LONG_PRESS: return "udfps"; 383 case REASON_SENSOR_QUICK_PICKUP: return "quickPickup"; 384 default: throw new IllegalArgumentException("invalid reason: " + pulseReason); 385 } 386 } 387 388 @Retention(RetentionPolicy.SOURCE) 389 @IntDef({PULSE_REASON_NONE, PULSE_REASON_INTENT, PULSE_REASON_NOTIFICATION, 390 PULSE_REASON_SENSOR_SIGMOTION, REASON_SENSOR_PICKUP, REASON_SENSOR_DOUBLE_TAP, 391 PULSE_REASON_SENSOR_LONG_PRESS, PULSE_REASON_DOCKING, REASON_SENSOR_WAKE_UP, 392 PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN, REASON_SENSOR_TAP, 393 REASON_SENSOR_UDFPS_LONG_PRESS, REASON_SENSOR_QUICK_PICKUP}) 394 public @interface Reason {} 395 public static final int PULSE_REASON_NONE = -1; 396 public static final int PULSE_REASON_INTENT = 0; 397 public static final int PULSE_REASON_NOTIFICATION = 1; 398 public static final int PULSE_REASON_SENSOR_SIGMOTION = 2; 399 public static final int REASON_SENSOR_PICKUP = 3; 400 public static final int REASON_SENSOR_DOUBLE_TAP = 4; 401 public static final int PULSE_REASON_SENSOR_LONG_PRESS = 5; 402 public static final int PULSE_REASON_DOCKING = 6; 403 public static final int REASON_SENSOR_WAKE_UP = 7; 404 public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8; 405 public static final int REASON_SENSOR_TAP = 9; 406 public static final int REASON_SENSOR_UDFPS_LONG_PRESS = 10; 407 public static final int REASON_SENSOR_QUICK_PICKUP = 11; 408 409 public static final int TOTAL_REASONS = 12; 410 } 411