1 /* 2 * Copyright (C) 2022 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.display; 18 19 import android.annotation.IntDef; 20 import android.hardware.display.DisplayManagerInternal; 21 import android.util.Slog; 22 23 import com.android.internal.annotations.VisibleForTesting; 24 import com.android.server.display.utils.DebugUtils; 25 26 import java.io.PrintWriter; 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * A utility class to acquire/release suspend blockers and manage appropriate states around it. 32 * It is also a channel to asynchronously update the PowerManagerService about the changes in the 33 * display states as needed. 34 */ 35 public final class WakelockController { 36 public static final int WAKE_LOCK_PROXIMITY_POSITIVE = 1; 37 public static final int WAKE_LOCK_PROXIMITY_NEGATIVE = 2; 38 public static final int WAKE_LOCK_PROXIMITY_DEBOUNCE = 3; 39 public static final int WAKE_LOCK_STATE_CHANGED = 4; 40 public static final int WAKE_LOCK_UNFINISHED_BUSINESS = 5; 41 42 @VisibleForTesting 43 static final int WAKE_LOCK_MAX = WAKE_LOCK_UNFINISHED_BUSINESS; 44 45 private static final String TAG = "WakelockController"; 46 47 // To enable these logs, run: 48 // 'adb shell setprop persist.log.tag.WakelockController DEBUG && adb reboot' 49 private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); 50 51 @IntDef(flag = true, prefix = "WAKE_LOCK_", value = { 52 WAKE_LOCK_PROXIMITY_POSITIVE, 53 WAKE_LOCK_PROXIMITY_NEGATIVE, 54 WAKE_LOCK_PROXIMITY_DEBOUNCE, 55 WAKE_LOCK_STATE_CHANGED, 56 WAKE_LOCK_UNFINISHED_BUSINESS 57 }) 58 @Retention(RetentionPolicy.SOURCE) 59 public @interface WAKE_LOCK_TYPE { 60 } 61 62 // Asynchronous callbacks into the power manager service. 63 // Only invoked from the handler thread while no locks are held. 64 private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; 65 66 // Identifiers for suspend blocker acquisition requests 67 private final String mSuspendBlockerIdUnfinishedBusiness; 68 private final String mSuspendBlockerIdOnStateChanged; 69 private final String mSuspendBlockerIdProxPositive; 70 private final String mSuspendBlockerIdProxNegative; 71 private final String mSuspendBlockerIdProxDebounce; 72 73 // True if we have unfinished business and are holding a suspend-blocker. 74 private boolean mUnfinishedBusiness; 75 76 // True if we have have debounced the proximity change impact and are holding a suspend-blocker. 77 private boolean mHasProximityDebounced; 78 79 // The ID of the LogicalDisplay tied to this. 80 private final int mDisplayId; 81 private final String mTag; 82 83 // When true, it implies a wakelock is being held to guarantee the update happens before we 84 // collapse into suspend and so needs to be cleaned up if the thread is exiting. 85 // Should only be accessed on the Handler thread of the class managing the Display states 86 // (i.e. DisplayPowerController2). 87 private boolean mOnStateChangedPending; 88 89 // When true, it implies that a positive proximity wakelock is currently held. Used to keep 90 // track if suspend blocker acquisitions is pending when shutting down the 91 // DisplayPowerController2. Should only be accessed on the Handler thread of the class 92 // managing the Display states (i.e. DisplayPowerController2). 93 private boolean mIsProximityPositiveAcquired; 94 95 // When true, it implies that a negative proximity wakelock is currently held. Used to keep 96 // track if suspend blocker acquisitions is pending when shutting down the 97 // DisplayPowerController2. Should only be accessed on the Handler thread of the class 98 // managing the Display states (i.e. DisplayPowerController2). 99 private boolean mIsProximityNegativeAcquired; 100 101 /** 102 * The constructor of WakelockController. Manages the initialization of all the local entities 103 * needed for its appropriate functioning. 104 */ WakelockController(int displayId, DisplayManagerInternal.DisplayPowerCallbacks callbacks)105 public WakelockController(int displayId, 106 DisplayManagerInternal.DisplayPowerCallbacks callbacks) { 107 mDisplayId = displayId; 108 mTag = TAG + "[" + mDisplayId + "]"; 109 mDisplayPowerCallbacks = callbacks; 110 mSuspendBlockerIdUnfinishedBusiness = "[" + displayId + "]unfinished business"; 111 mSuspendBlockerIdOnStateChanged = "[" + displayId + "]on state changed"; 112 mSuspendBlockerIdProxPositive = "[" + displayId + "]prox positive"; 113 mSuspendBlockerIdProxNegative = "[" + displayId + "]prox negative"; 114 mSuspendBlockerIdProxDebounce = "[" + displayId + "]prox debounce"; 115 } 116 117 /** 118 * A utility to acquire a wakelock 119 * 120 * @param wakelock The type of Wakelock to be acquired 121 * @return True of the wakelock is successfully acquired. False if it is already acquired 122 */ acquireWakelock(@AKE_LOCK_TYPE int wakelock)123 public boolean acquireWakelock(@WAKE_LOCK_TYPE int wakelock) { 124 return acquireWakelockInternal(wakelock); 125 } 126 127 /** 128 * A utility to release a wakelock 129 * 130 * @param wakelock The type of Wakelock to be released 131 * @return True of an acquired wakelock is successfully released. False if it is already 132 * acquired 133 */ releaseWakelock(@AKE_LOCK_TYPE int wakelock)134 public boolean releaseWakelock(@WAKE_LOCK_TYPE int wakelock) { 135 return releaseWakelockInternal(wakelock); 136 } 137 138 /** 139 * A utility to release all the wakelock acquired by the system 140 */ releaseAll()141 public void releaseAll() { 142 for (int i = WAKE_LOCK_PROXIMITY_POSITIVE; i <= WAKE_LOCK_MAX; i++) { 143 releaseWakelockInternal(i); 144 } 145 } 146 acquireWakelockInternal(@AKE_LOCK_TYPE int wakelock)147 private boolean acquireWakelockInternal(@WAKE_LOCK_TYPE int wakelock) { 148 switch (wakelock) { 149 case WAKE_LOCK_PROXIMITY_POSITIVE: 150 return acquireProxPositiveSuspendBlocker(); 151 case WAKE_LOCK_PROXIMITY_NEGATIVE: 152 return acquireProxNegativeSuspendBlocker(); 153 case WAKE_LOCK_PROXIMITY_DEBOUNCE: 154 return acquireProxDebounceSuspendBlocker(); 155 case WAKE_LOCK_STATE_CHANGED: 156 return acquireStateChangedSuspendBlocker(); 157 case WAKE_LOCK_UNFINISHED_BUSINESS: 158 return acquireUnfinishedBusinessSuspendBlocker(); 159 default: 160 throw new RuntimeException("Invalid wakelock attempted to be acquired"); 161 } 162 } 163 releaseWakelockInternal(@AKE_LOCK_TYPE int wakelock)164 private boolean releaseWakelockInternal(@WAKE_LOCK_TYPE int wakelock) { 165 switch (wakelock) { 166 case WAKE_LOCK_PROXIMITY_POSITIVE: 167 return releaseProxPositiveSuspendBlocker(); 168 case WAKE_LOCK_PROXIMITY_NEGATIVE: 169 return releaseProxNegativeSuspendBlocker(); 170 case WAKE_LOCK_PROXIMITY_DEBOUNCE: 171 return releaseProxDebounceSuspendBlocker(); 172 case WAKE_LOCK_STATE_CHANGED: 173 return releaseStateChangedSuspendBlocker(); 174 case WAKE_LOCK_UNFINISHED_BUSINESS: 175 return releaseUnfinishedBusinessSuspendBlocker(); 176 default: 177 throw new RuntimeException("Invalid wakelock attempted to be released"); 178 } 179 } 180 181 /** 182 * Acquires the proximity positive wakelock and notifies the PowerManagerService about the 183 * changes. 184 */ acquireProxPositiveSuspendBlocker()185 private boolean acquireProxPositiveSuspendBlocker() { 186 if (!mIsProximityPositiveAcquired) { 187 mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxPositive); 188 mIsProximityPositiveAcquired = true; 189 return true; 190 } 191 return false; 192 } 193 194 /** 195 * Acquires the state change wakelock and notifies the PowerManagerService about the changes. 196 */ acquireStateChangedSuspendBlocker()197 private boolean acquireStateChangedSuspendBlocker() { 198 // Grab a wake lock if we have change of the display state 199 if (!mOnStateChangedPending) { 200 if (DEBUG) { 201 Slog.d(mTag, "State Changed..."); 202 } 203 mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerIdOnStateChanged); 204 mOnStateChangedPending = true; 205 return true; 206 } 207 return false; 208 } 209 210 /** 211 * Releases the state change wakelock and notifies the PowerManagerService about the changes. 212 */ releaseStateChangedSuspendBlocker()213 private boolean releaseStateChangedSuspendBlocker() { 214 if (mOnStateChangedPending) { 215 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdOnStateChanged); 216 mOnStateChangedPending = false; 217 return true; 218 } 219 return false; 220 } 221 222 /** 223 * Acquires the unfinished business wakelock and notifies the PowerManagerService about the 224 * changes. 225 */ acquireUnfinishedBusinessSuspendBlocker()226 private boolean acquireUnfinishedBusinessSuspendBlocker() { 227 // Grab a wake lock if we have unfinished business. 228 if (!mUnfinishedBusiness) { 229 if (DEBUG) { 230 Slog.d(mTag, "Unfinished business..."); 231 } 232 mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness); 233 mUnfinishedBusiness = true; 234 return true; 235 } 236 return false; 237 } 238 239 /** 240 * Releases the unfinished business wakelock and notifies the PowerManagerService about the 241 * changes. 242 */ releaseUnfinishedBusinessSuspendBlocker()243 private boolean releaseUnfinishedBusinessSuspendBlocker() { 244 if (mUnfinishedBusiness) { 245 if (DEBUG) { 246 Slog.d(mTag, "Finished business..."); 247 } 248 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdUnfinishedBusiness); 249 mUnfinishedBusiness = false; 250 return true; 251 } 252 return false; 253 } 254 255 /** 256 * Releases the proximity positive wakelock and notifies the PowerManagerService about the 257 * changes. 258 */ releaseProxPositiveSuspendBlocker()259 private boolean releaseProxPositiveSuspendBlocker() { 260 if (mIsProximityPositiveAcquired) { 261 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxPositive); 262 mIsProximityPositiveAcquired = false; 263 return true; 264 } 265 return false; 266 } 267 268 /** 269 * Acquires the proximity negative wakelock and notifies the PowerManagerService about the 270 * changes. 271 */ acquireProxNegativeSuspendBlocker()272 private boolean acquireProxNegativeSuspendBlocker() { 273 if (!mIsProximityNegativeAcquired) { 274 mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxNegative); 275 mIsProximityNegativeAcquired = true; 276 return true; 277 } 278 return false; 279 } 280 281 /** 282 * Releases the proximity negative wakelock and notifies the PowerManagerService about the 283 * changes. 284 */ releaseProxNegativeSuspendBlocker()285 private boolean releaseProxNegativeSuspendBlocker() { 286 if (mIsProximityNegativeAcquired) { 287 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxNegative); 288 mIsProximityNegativeAcquired = false; 289 return true; 290 } 291 return false; 292 } 293 294 /** 295 * Acquires the proximity debounce wakelock and notifies the PowerManagerService about the 296 * changes. 297 */ acquireProxDebounceSuspendBlocker()298 private boolean acquireProxDebounceSuspendBlocker() { 299 if (!mHasProximityDebounced) { 300 mDisplayPowerCallbacks.acquireSuspendBlocker(mSuspendBlockerIdProxDebounce); 301 mHasProximityDebounced = true; 302 return true; 303 } 304 return false; 305 } 306 307 /** 308 * Releases the proximity debounce wakelock and notifies the PowerManagerService about the 309 * changes. 310 */ releaseProxDebounceSuspendBlocker()311 private boolean releaseProxDebounceSuspendBlocker() { 312 if (mHasProximityDebounced) { 313 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxDebounce); 314 mHasProximityDebounced = false; 315 return true; 316 } 317 return false; 318 } 319 320 /** 321 * Gets the Runnable to be executed when the proximity becomes positive. 322 */ getOnProximityPositiveRunnable()323 public Runnable getOnProximityPositiveRunnable() { 324 return () -> { 325 if (mIsProximityPositiveAcquired) { 326 mIsProximityPositiveAcquired = false; 327 mDisplayPowerCallbacks.onProximityPositive(); 328 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxPositive); 329 } 330 }; 331 } 332 333 /** 334 * Gets the Runnable to be executed when the display state changes 335 */ 336 public Runnable getOnStateChangedRunnable() { 337 return () -> { 338 if (mOnStateChangedPending) { 339 mOnStateChangedPending = false; 340 mDisplayPowerCallbacks.onStateChanged(); 341 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdOnStateChanged); 342 } 343 }; 344 } 345 346 /** 347 * Gets the Runnable to be executed when the proximity becomes negative. 348 */ 349 public Runnable getOnProximityNegativeRunnable() { 350 return () -> { 351 if (mIsProximityNegativeAcquired) { 352 mIsProximityNegativeAcquired = false; 353 mDisplayPowerCallbacks.onProximityNegative(); 354 mDisplayPowerCallbacks.releaseSuspendBlocker(mSuspendBlockerIdProxNegative); 355 } 356 }; 357 } 358 359 /** 360 * Dumps the current state of this 361 */ 362 public void dumpLocal(PrintWriter pw) { 363 pw.println("WakelockController State:"); 364 pw.println(" mDisplayId=" + mDisplayId); 365 pw.println(" mUnfinishedBusiness=" + hasUnfinishedBusiness()); 366 pw.println(" mOnStateChangePending=" + isOnStateChangedPending()); 367 pw.println(" mOnProximityPositiveMessages=" + isProximityPositiveAcquired()); 368 pw.println(" mOnProximityNegativeMessages=" + isProximityNegativeAcquired()); 369 } 370 371 @VisibleForTesting 372 String getSuspendBlockerUnfinishedBusinessId() { 373 return mSuspendBlockerIdUnfinishedBusiness; 374 } 375 376 @VisibleForTesting 377 String getSuspendBlockerOnStateChangedId() { 378 return mSuspendBlockerIdOnStateChanged; 379 } 380 381 @VisibleForTesting 382 String getSuspendBlockerProxPositiveId() { 383 return mSuspendBlockerIdProxPositive; 384 } 385 386 @VisibleForTesting 387 String getSuspendBlockerProxNegativeId() { 388 return mSuspendBlockerIdProxNegative; 389 } 390 391 @VisibleForTesting 392 String getSuspendBlockerProxDebounceId() { 393 return mSuspendBlockerIdProxDebounce; 394 } 395 396 @VisibleForTesting 397 boolean hasUnfinishedBusiness() { 398 return mUnfinishedBusiness; 399 } 400 401 @VisibleForTesting 402 boolean isOnStateChangedPending() { 403 return mOnStateChangedPending; 404 } 405 406 @VisibleForTesting 407 boolean isProximityPositiveAcquired() { 408 return mIsProximityPositiveAcquired; 409 } 410 411 @VisibleForTesting 412 boolean isProximityNegativeAcquired() { 413 return mIsProximityNegativeAcquired; 414 } 415 416 @VisibleForTesting 417 boolean hasProximitySensorDebounced() { 418 return mHasProximityDebounced; 419 } 420 } 421