1 /* 2 * Copyright 2024 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.server.power; 18 19 import static android.os.PowerManager.USER_ACTIVITY_EVENT_OTHER; 20 import static android.os.PowerManagerInternal.isInteractive; 21 22 import static com.android.server.power.PowerManagerService.DEFAULT_SCREEN_OFF_TIMEOUT; 23 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_NON_INTERACTIVE; 24 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_SCREEN_LOCK; 25 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN; 26 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY; 27 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_ATTENTION; 28 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_BUTTON; 29 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_OTHER; 30 import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_TOUCH; 31 32 import android.annotation.IntDef; 33 import android.app.ActivityManager; 34 import android.app.SynchronousUserSwitchObserver; 35 import android.content.Context; 36 import android.database.ContentObserver; 37 import android.os.Handler; 38 import android.os.PowerManager; 39 import android.os.PowerManagerInternal; 40 import android.os.RemoteException; 41 import android.os.SystemClock; 42 import android.os.UserHandle; 43 import android.provider.Settings; 44 import android.util.IndentingPrintWriter; 45 import android.util.SparseArray; 46 import android.view.Display; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 import com.android.internal.util.FrameworkStatsLog; 50 51 import java.io.PrintWriter; 52 import java.lang.annotation.Retention; 53 import java.lang.annotation.RetentionPolicy; 54 55 /** 56 * Observe the wakefulness session of the device, tracking the reason and the 57 * last user activity when the interactive state is off. 58 */ 59 public class WakefulnessSessionObserver { 60 private static final String TAG = "WakefulnessSessionObserver"; 61 62 private static final int OFF_REASON_UNKNOWN = FrameworkStatsLog 63 .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__UNKNOWN; 64 private static final int OFF_REASON_TIMEOUT = FrameworkStatsLog 65 .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__TIMEOUT; 66 @VisibleForTesting 67 protected static final int OFF_REASON_POWER_BUTTON = FrameworkStatsLog 68 .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__POWER_BUTTON; 69 70 /** 71 * Interactive off reason 72 * {@link android.os.statsd.power.ScreenInteractiveSessionReported.InteractiveStateOffReason}. 73 */ 74 @IntDef(prefix = {"OFF_REASON_"}, value = { 75 OFF_REASON_UNKNOWN, 76 OFF_REASON_TIMEOUT, 77 OFF_REASON_POWER_BUTTON 78 }) 79 @Retention(RetentionPolicy.SOURCE) 80 private @interface OffReason {} 81 82 private static final int OVERRIDE_OUTCOME_UNKNOWN = FrameworkStatsLog 83 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__UNKNOWN; 84 @VisibleForTesting 85 protected static final int OVERRIDE_OUTCOME_TIMEOUT_SUCCESS = FrameworkStatsLog 86 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__TIMEOUT_SUCCESS; 87 @VisibleForTesting 88 protected static final int OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT = FrameworkStatsLog 89 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__TIMEOUT_USER_INITIATED_REVERT; 90 private static final int OVERRIDE_OUTCOME_CANCEL_CLIENT_API_CALL = FrameworkStatsLog 91 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_CLIENT_API_CALL; 92 @VisibleForTesting 93 protected static final int OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION = FrameworkStatsLog 94 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_USER_INTERACTION; 95 @VisibleForTesting 96 protected static final int OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON = FrameworkStatsLog 97 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_POWER_BUTTON; 98 private static final int OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT = FrameworkStatsLog 99 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_CLIENT_DISCONNECTED; 100 private static final int OVERRIDE_OUTCOME_CANCEL_OTHER = FrameworkStatsLog 101 .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_OTHER; 102 103 /** 104 * Override Outcome 105 * {@link android.os.statsd.power.ScreenTimeoutOverrideReported.OverrideOutcome}. 106 */ 107 @IntDef(prefix = {"OVERRIDE_OUTCOME_"}, value = { 108 OVERRIDE_OUTCOME_UNKNOWN, 109 OVERRIDE_OUTCOME_TIMEOUT_SUCCESS, 110 OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT, 111 OVERRIDE_OUTCOME_CANCEL_CLIENT_API_CALL, 112 OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION, 113 OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON, 114 OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT, 115 OVERRIDE_OUTCOME_CANCEL_OTHER 116 }) 117 @Retention(RetentionPolicy.SOURCE) 118 private @interface OverrideOutcome {} 119 120 private static final int DEFAULT_USER_ACTIVITY = USER_ACTIVITY_EVENT_OTHER; 121 private static final long TIMEOUT_USER_INITIATED_REVERT_THRESHOLD_MILLIS = 5000L; 122 private static final long SEND_OVERRIDE_TIMEOUT_LOG_THRESHOLD_MILLIS = 1000L; 123 124 private Context mContext; 125 private int mScreenOffTimeoutMs; 126 private int mOverrideTimeoutMs = 0; 127 @VisibleForTesting 128 protected final SparseArray<WakefulnessSessionPowerGroup> mPowerGroups = new SparseArray<>(); 129 @VisibleForTesting 130 protected WakefulnessSessionFrameworkStatsLogger mWakefulnessSessionFrameworkStatsLogger; 131 private final Clock mClock; 132 private final Object mLock = new Object(); 133 WakefulnessSessionObserver(Context context, Injector injector)134 public WakefulnessSessionObserver(Context context, Injector injector) { 135 if (injector == null) { 136 injector = new Injector(); 137 } 138 139 mContext = context; 140 mWakefulnessSessionFrameworkStatsLogger = injector 141 .getWakefulnessSessionFrameworkStatsLogger(); 142 mClock = injector.getClock(); 143 updateSettingScreenOffTimeout(context); 144 145 try { 146 final UserSwitchObserver observer = new UserSwitchObserver(); 147 ActivityManager.getService().registerUserSwitchObserver(observer, TAG); 148 } catch (RemoteException e) { 149 // Shouldn't happen since in-process. 150 } 151 152 mOverrideTimeoutMs = mContext.getResources().getInteger( 153 com.android.internal.R.integer.config_screenTimeoutOverride); 154 155 mContext.getContentResolver() 156 .registerContentObserver( 157 Settings.System.getUriFor(Settings.System.SCREEN_OFF_TIMEOUT), 158 false, 159 new ContentObserver(new Handler(mContext.getMainLooper())) { 160 @Override 161 public void onChange(boolean selfChange) { 162 updateSettingScreenOffTimeout(mContext); 163 } 164 }, 165 UserHandle.USER_ALL); 166 167 mPowerGroups.append( 168 Display.DEFAULT_DISPLAY_GROUP, 169 new WakefulnessSessionPowerGroup(Display.DEFAULT_DISPLAY_GROUP)); 170 } 171 172 /** 173 * Track the user activity event. 174 * 175 * @param eventTime Activity time, in uptime millis. 176 * @param powerGroupId Power Group Id for this user activity 177 * @param event Activity type as defined in {@link PowerManager}. {@link 178 * android.hardware.display.DisplayManagerInternal.DisplayPowerRequest} 179 */ notifyUserActivity( long eventTime, int powerGroupId, @PowerManager.UserActivityEvent int event)180 public void notifyUserActivity( 181 long eventTime, int powerGroupId, @PowerManager.UserActivityEvent int event) { 182 if (!mPowerGroups.contains(powerGroupId)) { 183 mPowerGroups.append(powerGroupId, new WakefulnessSessionPowerGroup(powerGroupId)); 184 } 185 mPowerGroups.get(powerGroupId).notifyUserActivity(eventTime, event); 186 } 187 188 /** 189 * Track the system wakefulness 190 * 191 * @param powerGroupId Power Group Id for this wakefulness changes 192 * @param wakefulness Wakefulness as defined in {@link PowerManagerInternal} 193 * @param changeReason Reason of the go to sleep in 194 * {@link PowerManager.GoToSleepReason} or {@link PowerManager.WakeReason} 195 * @param eventTime timestamp of the wakefulness changes 196 */ onWakefulnessChangeStarted(int powerGroupId, int wakefulness, int changeReason, long eventTime)197 public void onWakefulnessChangeStarted(int powerGroupId, int wakefulness, int changeReason, 198 long eventTime) { 199 if (!mPowerGroups.contains(powerGroupId)) { 200 mPowerGroups.append(powerGroupId, new WakefulnessSessionPowerGroup(powerGroupId)); 201 } 202 mPowerGroups.get(powerGroupId).onWakefulnessChangeStarted(wakefulness, changeReason, 203 eventTime); 204 } 205 206 /** 207 * Track the acquired wakelocks 208 * 209 * @param flags wakelocks to be acquired {@link PowerManager} 210 */ onWakeLockAcquired(int flags)211 public void onWakeLockAcquired(int flags) { 212 int maskedFlag = flags & PowerManager.WAKE_LOCK_LEVEL_MASK; 213 if (maskedFlag == PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) { 214 for (int idx = 0; idx < mPowerGroups.size(); idx++) { 215 mPowerGroups.valueAt(idx).acquireTimeoutOverrideWakeLock(); 216 } 217 } 218 } 219 220 /** 221 * Track the released wakelocks 222 * 223 * @param flags wakelocks to be released {@link PowerManager} 224 * @param releaseReason the reason to release wakelock 225 * {@link ScreenTimeoutOverridePolicy.ReleaseReason} 226 */ onWakeLockReleased(int flags, int releaseReason)227 public void onWakeLockReleased(int flags, int releaseReason) { 228 int maskedFlag = flags & PowerManager.WAKE_LOCK_LEVEL_MASK; 229 if (maskedFlag == PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) { 230 for (int idx = 0; idx < mPowerGroups.size(); idx++) { 231 mPowerGroups.valueAt(idx).releaseTimeoutOverrideWakeLock(releaseReason); 232 } 233 } 234 } 235 236 /** 237 * Remove the inactive power group 238 * 239 * @param powerGroupId Power Group Id that should be removed 240 */ removePowerGroup(int powerGroupId)241 public void removePowerGroup(int powerGroupId) { 242 if (mPowerGroups.contains((powerGroupId))) { 243 mPowerGroups.delete(powerGroupId); 244 } 245 } 246 dump(PrintWriter writer)247 void dump(PrintWriter writer) { 248 writer.println(); 249 writer.println("Wakefulness Session Observer:"); 250 writer.println("default timeout: " + mScreenOffTimeoutMs); 251 writer.println("override timeout: " + mOverrideTimeoutMs); 252 IndentingPrintWriter indentingPrintWriter = new IndentingPrintWriter(writer); 253 indentingPrintWriter.increaseIndent(); 254 for (int idx = 0; idx < mPowerGroups.size(); idx++) { 255 mPowerGroups.valueAt(idx).dump(indentingPrintWriter); 256 } 257 writer.println(); 258 } 259 updateSettingScreenOffTimeout(Context context)260 private void updateSettingScreenOffTimeout(Context context) { 261 synchronized (mLock) { 262 mScreenOffTimeoutMs = Settings.System.getIntForUser( 263 context.getContentResolver(), 264 Settings.System.SCREEN_OFF_TIMEOUT, 265 DEFAULT_SCREEN_OFF_TIMEOUT, 266 UserHandle.USER_CURRENT); 267 } 268 } 269 getScreenOffTimeout()270 private int getScreenOffTimeout() { 271 synchronized (mLock) { 272 return mScreenOffTimeoutMs; 273 } 274 } 275 276 /** Screen Session by each power group */ 277 @VisibleForTesting 278 protected class WakefulnessSessionPowerGroup { 279 private static final long TIMEOUT_OFF_RESET_TIMESTAMP = -1; 280 281 private int mPowerGroupId; 282 private int mCurrentWakefulness; 283 private boolean mIsInteractive = false; 284 // state on start timestamp: will be used in state off to calculate the duration of state on 285 private long mInteractiveStateOnStartTimestamp; 286 @VisibleForTesting 287 protected long mCurrentUserActivityTimestamp; 288 @VisibleForTesting 289 protected @PowerManager.UserActivityEvent int mCurrentUserActivityEvent; 290 @VisibleForTesting 291 protected long mPrevUserActivityTimestamp; 292 @VisibleForTesting 293 protected @PowerManager.UserActivityEvent int mPrevUserActivityEvent; 294 // to track the Override Timeout is set (that is, on SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) 295 private int mTimeoutOverrideWakeLockCounter = 0; 296 // The timestamp when Override Timeout is set to false 297 private @ScreenTimeoutOverridePolicy.ReleaseReason int mTimeoutOverrideReleaseReason; 298 // The timestamp when state off by timeout occurs 299 // will set TIMEOUT_OFF_RESET_TIMESTAMP if state on or state off by power button 300 private long mTimeoutOffTimestamp; 301 // The timestamp for the latest logTimeoutOverrideEvent calling 302 private long mSendOverrideTimeoutLogTimestamp; 303 WakefulnessSessionPowerGroup(int powerGroupId)304 public WakefulnessSessionPowerGroup(int powerGroupId) { 305 mCurrentUserActivityEvent = DEFAULT_USER_ACTIVITY; 306 mCurrentUserActivityTimestamp = -1; 307 mPrevUserActivityEvent = DEFAULT_USER_ACTIVITY; 308 mPrevUserActivityTimestamp = -1; 309 mPowerGroupId = powerGroupId; 310 } 311 notifyUserActivity(long eventTime, @PowerManager.UserActivityEvent int event)312 public void notifyUserActivity(long eventTime, @PowerManager.UserActivityEvent int event) { 313 // only track when user activity changes 314 if (event == mCurrentUserActivityEvent) { 315 return; 316 } 317 mPrevUserActivityEvent = mCurrentUserActivityEvent; 318 mCurrentUserActivityEvent = event; 319 mPrevUserActivityTimestamp = mCurrentUserActivityTimestamp; 320 mCurrentUserActivityTimestamp = eventTime; 321 } 322 onWakefulnessChangeStarted(int wakefulness, int changeReason, long eventTime)323 public void onWakefulnessChangeStarted(int wakefulness, int changeReason, long eventTime) { 324 mCurrentWakefulness = wakefulness; 325 if (mIsInteractive == isInteractive(wakefulness)) { 326 return; 327 } 328 329 mIsInteractive = isInteractive(wakefulness); 330 if (mIsInteractive) { 331 mInteractiveStateOnStartTimestamp = eventTime; 332 333 // Log the outcome of screen timeout override (USER INITIATED REVERT), 334 // when user initiates to revert the screen off state in a short period. 335 if (mTimeoutOffTimestamp != TIMEOUT_OFF_RESET_TIMESTAMP) { 336 long offToOnDurationMs = eventTime - mTimeoutOffTimestamp; 337 if (offToOnDurationMs < TIMEOUT_USER_INITIATED_REVERT_THRESHOLD_MILLIS) { 338 mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent( 339 mPowerGroupId, 340 OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT, 341 mOverrideTimeoutMs, 342 getScreenOffTimeout()); 343 mSendOverrideTimeoutLogTimestamp = eventTime; 344 } 345 mTimeoutOffTimestamp = TIMEOUT_OFF_RESET_TIMESTAMP; 346 } 347 } else { 348 int lastUserActivity = mCurrentUserActivityEvent; 349 long lastUserActivityDurationMs = eventTime - mCurrentUserActivityTimestamp; 350 @OffReason int interactiveStateOffReason = OFF_REASON_UNKNOWN; 351 int reducedInteractiveStateOnDurationMs = 0; 352 353 if (changeReason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) { 354 interactiveStateOffReason = OFF_REASON_POWER_BUTTON; 355 356 // Power Off will be triggered by USER_ACTIVITY_EVENT_BUTTON 357 // The metric wants to record the previous activity before EVENT_BUTTON 358 lastUserActivity = mPrevUserActivityEvent; 359 lastUserActivityDurationMs = eventTime - mPrevUserActivityTimestamp; 360 361 if (isInOverrideTimeout() 362 || mTimeoutOverrideReleaseReason == RELEASE_REASON_USER_ACTIVITY_BUTTON 363 ) { 364 mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent( 365 mPowerGroupId, 366 OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON, 367 mOverrideTimeoutMs, 368 getScreenOffTimeout()); 369 mSendOverrideTimeoutLogTimestamp = eventTime; 370 mTimeoutOverrideReleaseReason = RELEASE_REASON_UNKNOWN; // reset the reason 371 } 372 } else if (changeReason == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) { 373 // Interactive Off reason is timeout 374 interactiveStateOffReason = OFF_REASON_TIMEOUT; 375 376 lastUserActivity = mCurrentUserActivityEvent; 377 lastUserActivityDurationMs = eventTime - mCurrentUserActivityTimestamp; 378 379 // Log the outcome of screen timeout override when the early screen 380 // timeout has been done successfully. 381 if (isInOverrideTimeout()) { 382 reducedInteractiveStateOnDurationMs = 383 getScreenOffTimeout() - mOverrideTimeoutMs; 384 385 mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent( 386 mPowerGroupId, 387 OVERRIDE_OUTCOME_TIMEOUT_SUCCESS, 388 mOverrideTimeoutMs, 389 getScreenOffTimeout()); 390 mSendOverrideTimeoutLogTimestamp = eventTime; 391 392 // Record a timestamp to track if the user initiates to revert from off 393 // state instantly 394 mTimeoutOffTimestamp = eventTime; 395 } 396 } 397 398 long interactiveStateOnDurationMs = 399 eventTime - mInteractiveStateOnStartTimestamp; 400 mWakefulnessSessionFrameworkStatsLogger.logSessionEvent( 401 mPowerGroupId, 402 interactiveStateOffReason, 403 interactiveStateOnDurationMs, 404 lastUserActivity, 405 lastUserActivityDurationMs, 406 reducedInteractiveStateOnDurationMs); 407 } 408 } 409 acquireTimeoutOverrideWakeLock()410 public void acquireTimeoutOverrideWakeLock() { 411 synchronized (mLock) { 412 mTimeoutOverrideWakeLockCounter++; 413 } 414 } 415 releaseTimeoutOverrideWakeLock( @creenTimeoutOverridePolicy.ReleaseReason int releaseReason)416 public void releaseTimeoutOverrideWakeLock( 417 @ScreenTimeoutOverridePolicy.ReleaseReason int releaseReason) { 418 synchronized (mLock) { 419 mTimeoutOverrideWakeLockCounter--; 420 } 421 422 if (!isInOverrideTimeout()) { 423 mTimeoutOverrideReleaseReason = releaseReason; 424 long now = mClock.uptimeMillis(); 425 426 // Log the outcome of screen timeout override (USER INTERACTIVE or DISCONNECT), 427 // when early screen timeout be canceled. 428 // Note: Set the threshold to avoid sending this log repeatly after other outcomes. 429 long sendOverrideTimeoutLogDuration = now - mSendOverrideTimeoutLogTimestamp; 430 boolean sendOverrideTimeoutLogSoon = sendOverrideTimeoutLogDuration 431 < SEND_OVERRIDE_TIMEOUT_LOG_THRESHOLD_MILLIS; 432 if (!sendOverrideTimeoutLogSoon) { 433 @OverrideOutcome int outcome = OVERRIDE_OUTCOME_UNKNOWN; 434 switch (releaseReason) { 435 case RELEASE_REASON_USER_ACTIVITY_ATTENTION: 436 case RELEASE_REASON_USER_ACTIVITY_OTHER: 437 case RELEASE_REASON_USER_ACTIVITY_BUTTON: 438 case RELEASE_REASON_USER_ACTIVITY_TOUCH: 439 case RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY: 440 outcome = OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION; 441 break; 442 case RELEASE_REASON_SCREEN_LOCK: 443 case RELEASE_REASON_NON_INTERACTIVE: 444 outcome = OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT; 445 break; 446 default: 447 outcome = OVERRIDE_OUTCOME_UNKNOWN; 448 } 449 mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent( 450 mPowerGroupId, 451 outcome, 452 mOverrideTimeoutMs, 453 getScreenOffTimeout()); 454 } 455 } 456 } 457 458 @VisibleForTesting 459 protected boolean isInOverrideTimeout() { 460 synchronized (mLock) { 461 return (mTimeoutOverrideWakeLockCounter > 0); 462 } 463 } 464 dump(IndentingPrintWriter writer)465 void dump(IndentingPrintWriter writer) { 466 final long now = mClock.uptimeMillis(); 467 468 writer.println("Wakefulness Session Power Group powerGroupId: " + mPowerGroupId); 469 writer.increaseIndent(); 470 writer.println("current wakefulness: " + mCurrentWakefulness); 471 writer.println("current user activity event: " + mCurrentUserActivityEvent); 472 final long currentUserActivityDurationMs = now - mCurrentUserActivityTimestamp; 473 writer.println("current user activity duration: " + currentUserActivityDurationMs); 474 writer.println("previous user activity event: " + mPrevUserActivityEvent); 475 final long prevUserActivityDurationMs = now - mPrevUserActivityTimestamp; 476 writer.println("previous user activity duration: " + prevUserActivityDurationMs); 477 writer.println("is in override timeout: " + isInOverrideTimeout()); 478 writer.decreaseIndent(); 479 } 480 } 481 482 /** Log screen session atoms */ 483 protected static class WakefulnessSessionFrameworkStatsLogger { logSessionEvent( int powerGroupId, @OffReason int interactiveStateOffReason, long interactiveStateOnDurationMs, @PowerManager.UserActivityEvent int userActivityEvent, long lastUserActivityEventDurationMs, int reducedInteractiveStateOnDurationMs)484 public void logSessionEvent( 485 int powerGroupId, 486 @OffReason int interactiveStateOffReason, 487 long interactiveStateOnDurationMs, 488 @PowerManager.UserActivityEvent int userActivityEvent, 489 long lastUserActivityEventDurationMs, 490 int reducedInteractiveStateOnDurationMs) { 491 int logUserActivityEvent = convertToLogUserActivityEvent(userActivityEvent); 492 FrameworkStatsLog.write( 493 FrameworkStatsLog.SCREEN_INTERACTIVE_SESSION_REPORTED, 494 powerGroupId, 495 interactiveStateOffReason, 496 interactiveStateOnDurationMs, 497 logUserActivityEvent, 498 lastUserActivityEventDurationMs, 499 (long) reducedInteractiveStateOnDurationMs); 500 } 501 logTimeoutOverrideEvent( int powerGroupId, @OverrideOutcome int overrideOutcome, int overrideTimeoutMs, int defaultTimeoutMs)502 public void logTimeoutOverrideEvent( 503 int powerGroupId, 504 @OverrideOutcome int overrideOutcome, 505 int overrideTimeoutMs, 506 int defaultTimeoutMs) { 507 FrameworkStatsLog.write( 508 FrameworkStatsLog.SCREEN_TIMEOUT_OVERRIDE_REPORTED, 509 powerGroupId, 510 overrideOutcome, 511 (long) overrideTimeoutMs, 512 (long) defaultTimeoutMs); 513 } 514 515 private static final int USER_ACTIVITY_OTHER = FrameworkStatsLog 516 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__OTHER; 517 518 private static final int USER_ACTIVITY_BUTTON = FrameworkStatsLog 519 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__BUTTON; 520 521 private static final int USER_ACTIVITY_TOUCH = FrameworkStatsLog 522 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__TOUCH; 523 524 private static final int USER_ACTIVITY_ACCESSIBILITY = FrameworkStatsLog 525 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__ACCESSIBILITY; 526 private static final int USER_ACTIVITY_ATTENTION = FrameworkStatsLog 527 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__ATTENTION; 528 private static final int USER_ACTIVITY_FACE_DOWN = FrameworkStatsLog 529 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__FACE_DOWN; 530 531 private static final int USER_ACTIVITY_DEVICE_STATE = FrameworkStatsLog 532 .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__DEVICE_STATE; 533 534 /** 535 * User Activity Event 536 * {@link android.os.statsd.power.ScreenInteractiveSessionReported.UserActivityEvent}. 537 */ 538 @IntDef(prefix = {"USER_ACTIVITY_"}, value = { 539 USER_ACTIVITY_OTHER, 540 USER_ACTIVITY_BUTTON, 541 USER_ACTIVITY_TOUCH, 542 USER_ACTIVITY_ACCESSIBILITY, 543 USER_ACTIVITY_ATTENTION, 544 USER_ACTIVITY_FACE_DOWN, 545 USER_ACTIVITY_DEVICE_STATE, 546 }) 547 @Retention(RetentionPolicy.SOURCE) 548 private @interface UserActivityEvent {} 549 convertToLogUserActivityEvent( @owerManager.UserActivityEvent int userActivity)550 private @UserActivityEvent int convertToLogUserActivityEvent( 551 @PowerManager.UserActivityEvent int userActivity) { 552 switch (userActivity) { 553 case PowerManager.USER_ACTIVITY_EVENT_OTHER: 554 return USER_ACTIVITY_OTHER; 555 case PowerManager.USER_ACTIVITY_EVENT_BUTTON: 556 return USER_ACTIVITY_BUTTON; 557 case PowerManager.USER_ACTIVITY_EVENT_TOUCH: 558 return USER_ACTIVITY_TOUCH; 559 case PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY: 560 return USER_ACTIVITY_ACCESSIBILITY; 561 case PowerManager.USER_ACTIVITY_EVENT_ATTENTION: 562 return USER_ACTIVITY_ATTENTION; 563 case PowerManager.USER_ACTIVITY_EVENT_FACE_DOWN: 564 return USER_ACTIVITY_FACE_DOWN; 565 case PowerManager.USER_ACTIVITY_EVENT_DEVICE_STATE: 566 return USER_ACTIVITY_DEVICE_STATE; 567 } 568 return USER_ACTIVITY_OTHER; 569 } 570 } 571 572 /** To observe and do actions if users switch */ 573 private final class UserSwitchObserver extends SynchronousUserSwitchObserver { 574 @Override onUserSwitching(int newUserId)575 public void onUserSwitching(int newUserId) throws RemoteException { 576 updateSettingScreenOffTimeout(mContext); 577 } 578 } 579 580 @VisibleForTesting 581 interface Clock { uptimeMillis()582 long uptimeMillis(); 583 } 584 585 @VisibleForTesting 586 static class Injector { getWakefulnessSessionFrameworkStatsLogger()587 WakefulnessSessionFrameworkStatsLogger getWakefulnessSessionFrameworkStatsLogger() { 588 return new WakefulnessSessionFrameworkStatsLogger(); 589 } 590 getClock()591 Clock getClock() { 592 return SystemClock::uptimeMillis; 593 } 594 } 595 } 596