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