1 /* 2 * Copyright (C) 2012 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 android.hardware.display; 18 19 20 import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM; 21 import static android.hardware.display.DisplayManager.EventType; 22 import static android.Manifest.permission.MANAGE_DISPLAYS; 23 import static android.view.Display.HdrCapabilities.HdrType; 24 25 import android.Manifest; 26 import android.annotation.CallbackExecutor; 27 import android.annotation.FlaggedApi; 28 import android.annotation.FloatRange; 29 import android.annotation.IntDef; 30 import android.annotation.LongDef; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.RequiresPermission; 34 import android.app.ActivityThread; 35 import android.app.PropertyInvalidatedCache; 36 import android.compat.annotation.UnsupportedAppUsage; 37 import android.content.Context; 38 import android.content.pm.ParceledListSlice; 39 import android.content.res.Resources; 40 import android.graphics.ColorSpace; 41 import android.graphics.Point; 42 import android.hardware.OverlayProperties; 43 import android.hardware.display.DisplayManager.DisplayListener; 44 import android.hardware.graphics.common.DisplayDecorationSupport; 45 import android.media.projection.IMediaProjection; 46 import android.media.projection.MediaProjection; 47 import android.os.Binder; 48 import android.os.Handler; 49 import android.os.HandlerExecutor; 50 import android.os.IBinder; 51 import android.os.Looper; 52 import android.os.RemoteException; 53 import android.os.ServiceManager; 54 import android.os.Trace; 55 import android.sysprop.DisplayProperties; 56 import android.text.TextUtils; 57 import android.util.Log; 58 import android.util.Pair; 59 import android.util.Slog; 60 import android.util.SparseArray; 61 import android.view.Display; 62 import android.view.DisplayAdjustments; 63 import android.view.DisplayInfo; 64 import android.view.Surface; 65 66 import com.android.internal.annotations.VisibleForTesting; 67 import com.android.server.display.feature.flags.Flags; 68 69 import java.lang.annotation.Retention; 70 import java.lang.annotation.RetentionPolicy; 71 import java.util.Collections; 72 import java.util.List; 73 import java.util.Objects; 74 import java.util.concurrent.CopyOnWriteArrayList; 75 import java.util.concurrent.Executor; 76 import java.util.concurrent.atomic.AtomicLong; 77 import java.util.function.Consumer; 78 79 /** 80 * Manager communication with the display manager service on behalf of 81 * an application process. You're probably looking for {@link DisplayManager}. 82 * 83 * @hide 84 */ 85 public final class DisplayManagerGlobal { 86 private static final String TAG = "DisplayManager"; 87 88 private static final String EXTRA_LOGGING_PACKAGE_NAME = 89 DisplayProperties.debug_vri_package().orElse(null); 90 private static String sCurrentPackageName = ActivityThread.currentPackageName(); 91 private static boolean sExtraDisplayListenerLogging = initExtraLogging(); 92 93 // To enable these logs, run: 94 // 'adb shell setprop persist.log.tag.DisplayManager DEBUG && adb reboot' 95 private static final boolean DEBUG = DisplayManager.DEBUG || sExtraDisplayListenerLogging; 96 97 // True if display info and display ids should be cached. 98 // 99 // FIXME: The cache is currently disabled because it's unclear whether we have the 100 // necessary guarantees that the caches will always be flushed before clients 101 // attempt to observe their new state. For example, depending on the order 102 // in which the binder transactions take place, we might have a problem where 103 // an application could start processing a configuration change due to a display 104 // orientation change before the display info cache has actually been invalidated. 105 private static final boolean USE_CACHE = false; 106 107 @IntDef(prefix = {"EVENT_DISPLAY_"}, flag = true, value = { 108 EVENT_DISPLAY_ADDED, 109 EVENT_DISPLAY_BASIC_CHANGED, 110 EVENT_DISPLAY_REMOVED, 111 EVENT_DISPLAY_BRIGHTNESS_CHANGED, 112 EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED, 113 EVENT_DISPLAY_CONNECTED, 114 EVENT_DISPLAY_DISCONNECTED, 115 EVENT_DISPLAY_REFRESH_RATE_CHANGED, 116 EVENT_DISPLAY_STATE_CHANGED, 117 EVENT_DISPLAY_COMMITTED_STATE_CHANGED 118 }) 119 @Retention(RetentionPolicy.SOURCE) 120 public @interface DisplayEvent {} 121 122 public static final int EVENT_DISPLAY_ADDED = 1; 123 public static final int EVENT_DISPLAY_BASIC_CHANGED = 2; 124 125 public static final int EVENT_DISPLAY_REMOVED = 3; 126 public static final int EVENT_DISPLAY_BRIGHTNESS_CHANGED = 4; 127 public static final int EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED = 5; 128 public static final int EVENT_DISPLAY_CONNECTED = 6; 129 public static final int EVENT_DISPLAY_DISCONNECTED = 7; 130 public static final int EVENT_DISPLAY_REFRESH_RATE_CHANGED = 8; 131 public static final int EVENT_DISPLAY_STATE_CHANGED = 9; 132 public static final int EVENT_DISPLAY_COMMITTED_STATE_CHANGED = 10; 133 134 135 @LongDef(prefix = {"INTERNAL_EVENT_FLAG_"}, flag = true, value = { 136 INTERNAL_EVENT_FLAG_DISPLAY_ADDED, 137 INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED, 138 INTERNAL_EVENT_FLAG_DISPLAY_REMOVED, 139 INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED, 140 INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED, 141 INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED, 142 INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE, 143 INTERNAL_EVENT_FLAG_DISPLAY_STATE, 144 INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED, 145 INTERNAL_EVENT_FLAG_DISPLAY_COMMITTED_STATE_CHANGED 146 }) 147 @Retention(RetentionPolicy.SOURCE) 148 public @interface InternalEventFlag {} 149 150 public static final long INTERNAL_EVENT_FLAG_DISPLAY_ADDED = 1L << 0; 151 public static final long INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED = 1L << 1; 152 public static final long INTERNAL_EVENT_FLAG_DISPLAY_REMOVED = 1L << 2; 153 public static final long INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED = 1L << 3; 154 public static final long INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED = 1L << 4; 155 public static final long INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 5; 156 public static final long INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 6; 157 public static final long INTERNAL_EVENT_FLAG_DISPLAY_STATE = 1L << 7; 158 public static final long INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED = 1L << 8; 159 public static final long INTERNAL_EVENT_FLAG_DISPLAY_COMMITTED_STATE_CHANGED = 1L << 9; 160 161 162 @UnsupportedAppUsage 163 private static DisplayManagerGlobal sInstance; 164 165 // Guarded by mLock 166 private boolean mDispatchNativeCallbacks = false; 167 private float mNativeCallbackReportedRefreshRate; 168 private final Object mLock = new Object(); 169 170 @UnsupportedAppUsage 171 private final IDisplayManager mDm; 172 173 private DisplayManagerCallback mCallback; 174 private @InternalEventFlag long mRegisteredInternalEventFlag = 0; 175 private final CopyOnWriteArrayList<DisplayListenerDelegate> mDisplayListeners = 176 new CopyOnWriteArrayList<>(); 177 178 private final CopyOnWriteArrayList<DisplayTopologyListenerDelegate> mTopologyListeners = 179 new CopyOnWriteArrayList<>(); 180 181 private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<>(); 182 private final ColorSpace mWideColorSpace; 183 private final OverlayProperties mOverlayProperties; 184 private int[] mDisplayIdCache; 185 186 private int mWifiDisplayScanNestCount; 187 188 private final Binder mToken = new Binder(); 189 190 // Guarded by mLock 191 private boolean mShouldImplicitlyRegisterRrChanges = false; 192 193 @VisibleForTesting DisplayManagerGlobal(IDisplayManager dm)194 public DisplayManagerGlobal(IDisplayManager dm) { 195 mDm = dm; 196 initExtraLogging(); 197 198 try { 199 mWideColorSpace = 200 ColorSpace.get( 201 ColorSpace.Named.values()[mDm.getPreferredWideGamutColorSpaceId()]); 202 mOverlayProperties = mDm.getOverlaySupport(); 203 } catch (RemoteException ex) { 204 throw ex.rethrowFromSystemServer(); 205 } 206 } 207 208 private PropertyInvalidatedCache<Integer, DisplayInfo> mDisplayCache = 209 new PropertyInvalidatedCache<>( 210 new PropertyInvalidatedCache.Args(MODULE_SYSTEM) 211 .maxEntries(8).api(CACHE_KEY_DISPLAY_INFO_API).isolateUids(false), 212 CACHE_KEY_DISPLAY_INFO_API, null) { 213 214 @Override 215 public DisplayInfo recompute(Integer id) { 216 try { 217 return mDm.getDisplayInfo(id); 218 } catch (RemoteException ex) { 219 throw ex.rethrowFromSystemServer(); 220 } 221 } 222 }; 223 224 /** 225 * Gets an instance of the display manager global singleton. 226 * 227 * This method is actually unsupported on Ravenwood, however to support 228 * {@link android.app.ResourcesManager} we make this method always return null. 229 * 230 * @return The display manager instance, may be null early in system startup 231 * before the display manager has been fully initialized. 232 */ 233 @UnsupportedAppUsage 234 // @RavenwoodIgnore(value = "null") getInstance()235 public static DisplayManagerGlobal getInstance() { 236 synchronized (DisplayManagerGlobal.class) { 237 if (sInstance == null) { 238 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); 239 if (b != null) { 240 sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b)); 241 } 242 } 243 return sInstance; 244 } 245 } 246 247 /** 248 * Get information about a particular logical display. 249 * 250 * @param displayId The logical display id. 251 * @return Information about the specified display, or null if it does not exist. 252 * This object belongs to an internal cache and should be treated as if it were immutable. 253 */ 254 @UnsupportedAppUsage getDisplayInfo(int displayId)255 public DisplayInfo getDisplayInfo(int displayId) { 256 synchronized (mLock) { 257 return getDisplayInfoLocked(displayId); 258 } 259 } 260 261 /** 262 * Gets information about a particular logical display 263 * See {@link getDisplayInfo}, but assumes that {@link mLock} is held 264 */ getDisplayInfoLocked(int displayId)265 private @Nullable DisplayInfo getDisplayInfoLocked(int displayId) { 266 DisplayInfo info = null; 267 if (mDisplayCache != null) { 268 info = mDisplayCache.query(displayId); 269 } else { 270 try { 271 info = mDm.getDisplayInfo(displayId); 272 } catch (RemoteException ex) { 273 ex.rethrowFromSystemServer(); 274 } 275 } 276 if (info == null) { 277 return null; 278 } 279 280 registerCallbackIfNeededLocked(); 281 282 if (DEBUG) { 283 Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info); 284 } 285 return info; 286 } 287 288 /** 289 * Gets all currently valid logical display ids. 290 * 291 * @return An array containing all display ids. 292 */ 293 @UnsupportedAppUsage getDisplayIds()294 public int[] getDisplayIds() { 295 return getDisplayIds(/* includeDisabled= */ false); 296 } 297 298 /** 299 * Gets all currently valid logical display ids. 300 * 301 * @param includeDisabled True if the returned list of displays includes disabled displays. 302 * @return An array containing all display ids. 303 */ getDisplayIds(boolean includeDisabled)304 public int[] getDisplayIds(boolean includeDisabled) { 305 try { 306 synchronized (mLock) { 307 if (USE_CACHE) { 308 if (mDisplayIdCache != null) { 309 return mDisplayIdCache; 310 } 311 } 312 313 int[] displayIds = mDm.getDisplayIds(includeDisabled); 314 if (USE_CACHE) { 315 mDisplayIdCache = displayIds; 316 } 317 registerCallbackIfNeededLocked(); 318 return displayIds; 319 } 320 } catch (RemoteException ex) { 321 throw ex.rethrowFromSystemServer(); 322 } 323 } 324 325 /** 326 * Check if specified UID's content is present on display and should be granted access to it. 327 * 328 * @param uid UID to be checked. 329 * @param displayId id of the display where presence of the content is checked. 330 * @return {@code true} if UID is present on display, {@code false} otherwise. 331 */ isUidPresentOnDisplay(int uid, int displayId)332 public boolean isUidPresentOnDisplay(int uid, int displayId) { 333 try { 334 return mDm.isUidPresentOnDisplay(uid, displayId); 335 } catch (RemoteException ex) { 336 throw ex.rethrowFromSystemServer(); 337 } 338 } 339 340 /** 341 * Gets information about a logical display. 342 * 343 * The display metrics may be adjusted to provide compatibility 344 * for legacy applications or limited screen areas. 345 * 346 * @param displayId The logical display id. 347 * @param daj The compatibility info and activityToken. 348 * @return The display object, or null if there is no display with the given id. 349 */ getCompatibleDisplay(int displayId, DisplayAdjustments daj)350 public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) { 351 DisplayInfo displayInfo = getDisplayInfo(displayId); 352 if (displayInfo == null) { 353 return null; 354 } 355 return new Display(this, displayId, displayInfo, daj); 356 } 357 358 /** 359 * Gets information about a logical display. 360 * 361 * The display metrics may be adjusted to provide compatibility 362 * for legacy applications or limited screen areas. 363 * 364 * @param displayId The logical display id. 365 * @param resources Resources providing compatibility info. 366 * @return The display object, or null if there is no display with the given id. 367 */ getCompatibleDisplay(int displayId, Resources resources)368 public Display getCompatibleDisplay(int displayId, Resources resources) { 369 DisplayInfo displayInfo = getDisplayInfo(displayId); 370 if (displayInfo == null) { 371 return null; 372 } 373 return new Display(this, displayId, displayInfo, resources); 374 } 375 376 /** 377 * Gets information about a logical display without applying any compatibility metrics. 378 * 379 * @param displayId The logical display id. 380 * @return The display object, or null if there is no display with the given id. 381 */ 382 @UnsupportedAppUsage getRealDisplay(int displayId)383 public Display getRealDisplay(int displayId) { 384 return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); 385 } 386 387 /** 388 * Register a listener for display-related changes. 389 * 390 * @param listener The listener that will be called when display changes occur. 391 * @param handler Handler for the thread that will be receiving the callbacks. May be null. 392 * If null, listener will use the handler for the current thread, and if still null, 393 * the handler for the main thread. 394 * If that is still null, a runtime exception will be thrown. 395 * @param packageName of the calling package. 396 * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events 397 * to be subscribed to. 398 */ registerDisplayListener(@onNull DisplayListener listener, @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask, String packageName, boolean isEventFilterExplicit)399 public void registerDisplayListener(@NonNull DisplayListener listener, 400 @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask, 401 String packageName, boolean isEventFilterExplicit) { 402 Looper looper = getLooperForHandler(handler); 403 Handler springBoard = new Handler(looper); 404 registerDisplayListener(listener, new HandlerExecutor(springBoard), internalEventFlagsMask, 405 packageName, isEventFilterExplicit); 406 } 407 408 /** 409 * Register a listener for display-related changes. 410 * 411 * @param listener The listener that will be called when display changes occur. 412 * @param handler Handler for the thread that will be receiving the callbacks. May be null. 413 * If null, listener will use the handler for the current thread, and if still null, 414 * the handler for the main thread. 415 * If that is still null, a runtime exception will be thrown. 416 * @param internalEventFlagsMask Mask of events to be listened to. 417 * @param packageName of the calling package. 418 */ registerDisplayListener(@onNull DisplayListener listener, @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask, String packageName)419 public void registerDisplayListener(@NonNull DisplayListener listener, 420 @Nullable Handler handler, @InternalEventFlag long internalEventFlagsMask, 421 String packageName) { 422 registerDisplayListener(listener, handler, internalEventFlagsMask, packageName, true); 423 } 424 425 426 /** 427 * Register a listener for display-related changes. 428 * 429 * @param listener The listener that will be called when display changes occur. 430 * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null. 431 * @param internalEventFlagsMask Mask of events to be listened to. 432 * @param packageName of the calling package. 433 * @param isEventFilterExplicit Indicates if the explicit events to be subscribed to 434 * were supplied or not 435 */ registerDisplayListener(@onNull DisplayListener listener, @NonNull Executor executor, @InternalEventFlag long internalEventFlagsMask, String packageName, boolean isEventFilterExplicit)436 public void registerDisplayListener(@NonNull DisplayListener listener, 437 @NonNull Executor executor, @InternalEventFlag long internalEventFlagsMask, 438 String packageName, boolean isEventFilterExplicit) { 439 if (listener == null) { 440 throw new IllegalArgumentException("listener must not be null"); 441 } 442 443 if (internalEventFlagsMask == 0) { 444 throw new IllegalArgumentException("The set of events to listen to must not be empty."); 445 } 446 447 if (extraLogging()) { 448 Slog.i(TAG, "Registering Display Listener: " 449 + Long.toBinaryString(internalEventFlagsMask) 450 + ", packageName: " + packageName); 451 } 452 453 synchronized (mLock) { 454 int index = findDisplayListenerLocked(listener); 455 if (index < 0) { 456 mDisplayListeners.add(new DisplayListenerDelegate(listener, executor, 457 internalEventFlagsMask, packageName, isEventFilterExplicit)); 458 registerCallbackIfNeededLocked(); 459 } else { 460 mDisplayListeners.get(index).setEventsMask(internalEventFlagsMask); 461 } 462 updateCallbackIfNeededLocked(); 463 maybeLogAllDisplayListeners(); 464 } 465 } 466 467 468 /** 469 * Registers all the clients to INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE events if qualified 470 */ registerForRefreshRateChanges()471 public void registerForRefreshRateChanges() { 472 if (!Flags.delayImplicitRrRegistrationUntilRrAccessed()) { 473 return; 474 } 475 synchronized (mLock) { 476 if (!mShouldImplicitlyRegisterRrChanges) { 477 mShouldImplicitlyRegisterRrChanges = true; 478 Slog.i(TAG, "Implicitly registering for refresh rate"); 479 updateCallbackIfNeededLocked(); 480 } 481 } 482 } 483 unregisterDisplayListener(DisplayListener listener)484 public void unregisterDisplayListener(DisplayListener listener) { 485 if (listener == null) { 486 throw new IllegalArgumentException("listener must not be null"); 487 } 488 489 if (extraLogging()) { 490 Slog.i(TAG, "Unregistering Display Listener: " + listener); 491 } 492 493 synchronized (mLock) { 494 int index = findDisplayListenerLocked(listener); 495 if (index >= 0) { 496 DisplayListenerDelegate d = mDisplayListeners.get(index); 497 d.clearEvents(); 498 mDisplayListeners.remove(index); 499 updateCallbackIfNeededLocked(); 500 } 501 } 502 maybeLogAllDisplayListeners(); 503 } 504 maybeLogAllDisplayListeners()505 private void maybeLogAllDisplayListeners() { 506 if (!extraLogging()) { 507 return; 508 } 509 510 Slog.i(TAG, "Currently Registered Display Listeners:"); 511 for (int i = 0; i < mDisplayListeners.size(); i++) { 512 Slog.i(TAG, i + ": " + mDisplayListeners.get(i)); 513 } 514 } 515 maybeLogAllTopologyListeners()516 private void maybeLogAllTopologyListeners() { 517 if (!extraLogging()) { 518 return; 519 } 520 Slog.i(TAG, "Currently registered display topology listeners:"); 521 int i = 0; 522 for (DisplayTopologyListenerDelegate d : mTopologyListeners) { 523 Slog.i(TAG, i + ": " + d); 524 i++; 525 } 526 } 527 528 /** 529 * Called when there is a display-related window configuration change. Reroutes the event from 530 * WindowManager to make sure the {@link Display} fields are up-to-date in the last callback. 531 * @param displayId the logical display that was changed. 532 */ handleDisplayChangeFromWindowManager(int displayId)533 public void handleDisplayChangeFromWindowManager(int displayId) { 534 // There can be racing condition between DMS and WMS callbacks, so force triggering the 535 // listener to make sure the client can get the onDisplayChanged callback even if 536 // DisplayInfo is not changed (Display read from both DisplayInfo and WindowConfiguration). 537 handleDisplayEvent(displayId, EVENT_DISPLAY_BASIC_CHANGED, true /* forceUpdate */); 538 } 539 getLooperForHandler(@ullable Handler handler)540 private static Looper getLooperForHandler(@Nullable Handler handler) { 541 Looper looper = handler != null ? handler.getLooper() : Looper.myLooper(); 542 if (looper == null) { 543 looper = Looper.getMainLooper(); 544 } 545 if (looper == null) { 546 throw new RuntimeException("Could not get Looper for the UI thread."); 547 } 548 return looper; 549 } 550 findDisplayListenerLocked(DisplayListener listener)551 private int findDisplayListenerLocked(DisplayListener listener) { 552 final int numListeners = mDisplayListeners.size(); 553 for (int i = 0; i < numListeners; i++) { 554 if (mDisplayListeners.get(i).mListener == listener) { 555 return i; 556 } 557 } 558 return -1; 559 } 560 561 @InternalEventFlag calculateEventsMaskLocked()562 private long calculateEventsMaskLocked() { 563 long mask = 0; 564 final int numListeners = mDisplayListeners.size(); 565 for (int i = 0; i < numListeners; i++) { 566 DisplayListenerDelegate displayListenerDelegate = mDisplayListeners.get(i); 567 if (!Flags.delayImplicitRrRegistrationUntilRrAccessed() 568 || mShouldImplicitlyRegisterRrChanges) { 569 displayListenerDelegate.implicitlyRegisterForRRChanges(); 570 } 571 mask |= displayListenerDelegate.mInternalEventFlagsMask; 572 } 573 574 if (mDispatchNativeCallbacks) { 575 mask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED 576 | INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED 577 | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE 578 | INTERNAL_EVENT_FLAG_DISPLAY_REMOVED; 579 } 580 if (!mTopologyListeners.isEmpty()) { 581 mask |= INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED; 582 } 583 return mask; 584 } 585 findTopologyListenerLocked( @onNull Consumer<DisplayTopology> listener)586 private DisplayTopologyListenerDelegate findTopologyListenerLocked( 587 @NonNull Consumer<DisplayTopology> listener) { 588 for (DisplayTopologyListenerDelegate delegate : mTopologyListeners) { 589 if (delegate.mListener == listener) { 590 return delegate; 591 } 592 } 593 return null; 594 } 595 registerCallbackIfNeededLocked()596 private void registerCallbackIfNeededLocked() { 597 if (mCallback == null) { 598 mCallback = new DisplayManagerCallback(); 599 updateCallbackIfNeededLocked(); 600 } 601 } 602 updateCallbackIfNeededLocked()603 private void updateCallbackIfNeededLocked() { 604 long mask = calculateEventsMaskLocked(); 605 if (DEBUG) { 606 Log.d(TAG, "Mask for listener: " + mask); 607 } 608 if (mask != mRegisteredInternalEventFlag) { 609 try { 610 mDm.registerCallbackWithEventMask(mCallback, mask); 611 mRegisteredInternalEventFlag = mask; 612 } catch (RemoteException ex) { 613 throw ex.rethrowFromSystemServer(); 614 } 615 } 616 } 617 handleDisplayEvent(int displayId, @DisplayEvent int event, boolean forceUpdate)618 private void handleDisplayEvent(int displayId, @DisplayEvent int event, boolean forceUpdate) { 619 final DisplayInfo info; 620 synchronized (mLock) { 621 if (USE_CACHE) { 622 mDisplayInfoCache.remove(displayId); 623 624 if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) { 625 mDisplayIdCache = null; 626 } 627 } 628 629 info = getDisplayInfoLocked(displayId); 630 if ((event == EVENT_DISPLAY_BASIC_CHANGED 631 || event == EVENT_DISPLAY_REFRESH_RATE_CHANGED) && mDispatchNativeCallbacks) { 632 // Choreographer only supports a single display, so only dispatch refresh rate 633 // changes for the default display. 634 if (displayId == Display.DEFAULT_DISPLAY) { 635 // We can likely save a binder hop if we attach the refresh rate onto the 636 // listener. 637 DisplayInfo display = getDisplayInfoLocked(displayId); 638 if (display != null 639 && mNativeCallbackReportedRefreshRate != display.getRefreshRate()) { 640 mNativeCallbackReportedRefreshRate = display.getRefreshRate(); 641 // Signal native callbacks if we ever set a refresh rate. 642 nSignalNativeCallbacks(mNativeCallbackReportedRefreshRate); 643 } 644 } 645 } 646 } 647 // Accepting an Executor means the listener may be synchronously invoked, so we must 648 // not be holding mLock when we do so 649 for (DisplayListenerDelegate listener : mDisplayListeners) { 650 listener.sendDisplayEvent(displayId, event, info, forceUpdate); 651 } 652 } 653 654 /** 655 * Enable a connected display that is currently disabled. 656 * @hide 657 */ 658 @RequiresPermission("android.permission.MANAGE_DISPLAYS") enableConnectedDisplay(int displayId)659 public void enableConnectedDisplay(int displayId) { 660 try { 661 mDm.enableConnectedDisplay(displayId); 662 } catch (RemoteException ex) { 663 Log.e(TAG, "Error trying to enable external display", ex); 664 } 665 } 666 667 668 /** 669 * Disable a connected display that is currently enabled. 670 * @hide 671 */ 672 @RequiresPermission("android.permission.MANAGE_DISPLAYS") disableConnectedDisplay(int displayId)673 public void disableConnectedDisplay(int displayId) { 674 try { 675 mDm.disableConnectedDisplay(displayId); 676 } catch (RemoteException ex) { 677 Log.e(TAG, "Error trying to enable external display", ex); 678 } 679 } 680 681 /** 682 * Request to power a display OFF or reset it to a power state it supposed to have. 683 * @param displayId the id of the display 684 * @param state one of {@link android.view.Display#STATE_UNKNOWN} (to reset the state to 685 * the one the display should have had now), {@link android.view.Display#STATE_OFF}. 686 * @return true if successful, false otherwise 687 * @hide 688 */ 689 @RequiresPermission("android.permission.MANAGE_DISPLAYS") requestDisplayPower(int displayId, int state)690 public boolean requestDisplayPower(int displayId, int state) { 691 try { 692 return mDm.requestDisplayPower(displayId, state); 693 } catch (RemoteException ex) { 694 Log.e(TAG, "Error trying to request display power:" 695 + " state=" + state, ex); 696 return false; 697 } 698 } 699 startWifiDisplayScan()700 public void startWifiDisplayScan() { 701 synchronized (mLock) { 702 if (mWifiDisplayScanNestCount++ == 0) { 703 registerCallbackIfNeededLocked(); 704 try { 705 mDm.startWifiDisplayScan(); 706 } catch (RemoteException ex) { 707 throw ex.rethrowFromSystemServer(); 708 } 709 } 710 } 711 } 712 stopWifiDisplayScan()713 public void stopWifiDisplayScan() { 714 synchronized (mLock) { 715 if (--mWifiDisplayScanNestCount == 0) { 716 try { 717 mDm.stopWifiDisplayScan(); 718 } catch (RemoteException ex) { 719 throw ex.rethrowFromSystemServer(); 720 } 721 } else if (mWifiDisplayScanNestCount < 0) { 722 Log.wtf(TAG, "Wifi display scan nest count became negative: " 723 + mWifiDisplayScanNestCount); 724 mWifiDisplayScanNestCount = 0; 725 } 726 } 727 } 728 connectWifiDisplay(String deviceAddress)729 public void connectWifiDisplay(String deviceAddress) { 730 if (deviceAddress == null) { 731 throw new IllegalArgumentException("deviceAddress must not be null"); 732 } 733 734 try { 735 mDm.connectWifiDisplay(deviceAddress); 736 } catch (RemoteException ex) { 737 throw ex.rethrowFromSystemServer(); 738 } 739 } 740 pauseWifiDisplay()741 public void pauseWifiDisplay() { 742 try { 743 mDm.pauseWifiDisplay(); 744 } catch (RemoteException ex) { 745 throw ex.rethrowFromSystemServer(); 746 } 747 } 748 resumeWifiDisplay()749 public void resumeWifiDisplay() { 750 try { 751 mDm.resumeWifiDisplay(); 752 } catch (RemoteException ex) { 753 throw ex.rethrowFromSystemServer(); 754 } 755 } 756 757 @UnsupportedAppUsage disconnectWifiDisplay()758 public void disconnectWifiDisplay() { 759 try { 760 mDm.disconnectWifiDisplay(); 761 } catch (RemoteException ex) { 762 throw ex.rethrowFromSystemServer(); 763 } 764 } 765 renameWifiDisplay(String deviceAddress, String alias)766 public void renameWifiDisplay(String deviceAddress, String alias) { 767 if (deviceAddress == null) { 768 throw new IllegalArgumentException("deviceAddress must not be null"); 769 } 770 771 try { 772 mDm.renameWifiDisplay(deviceAddress, alias); 773 } catch (RemoteException ex) { 774 throw ex.rethrowFromSystemServer(); 775 } 776 } 777 forgetWifiDisplay(String deviceAddress)778 public void forgetWifiDisplay(String deviceAddress) { 779 if (deviceAddress == null) { 780 throw new IllegalArgumentException("deviceAddress must not be null"); 781 } 782 783 try { 784 mDm.forgetWifiDisplay(deviceAddress); 785 } catch (RemoteException ex) { 786 throw ex.rethrowFromSystemServer(); 787 } 788 } 789 790 @UnsupportedAppUsage getWifiDisplayStatus()791 public WifiDisplayStatus getWifiDisplayStatus() { 792 try { 793 return mDm.getWifiDisplayStatus(); 794 } catch (RemoteException ex) { 795 throw ex.rethrowFromSystemServer(); 796 } 797 } 798 799 /** 800 * Sets the HDR types that have been disabled by user. 801 * @param userDisabledHdrTypes the HDR types to disable. The HDR types are any of 802 */ setUserDisabledHdrTypes(@drType int[] userDisabledHdrTypes)803 public void setUserDisabledHdrTypes(@HdrType int[] userDisabledHdrTypes) { 804 try { 805 mDm.setUserDisabledHdrTypes(userDisabledHdrTypes); 806 } catch (RemoteException ex) { 807 throw ex.rethrowFromSystemServer(); 808 } 809 } 810 811 /** 812 * Sets whether or not the user disabled HDR types are returned from 813 * {@link Display#getHdrCapabilities}. 814 * 815 * @param areUserDisabledHdrTypesAllowed If true, the user-disabled 816 * types are ignored and returned, if the display supports them. If 817 * false, the user-disabled types are taken into consideration and 818 * are never returned, even if the display supports them. 819 */ setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed)820 public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) { 821 try { 822 mDm.setAreUserDisabledHdrTypesAllowed(areUserDisabledHdrTypesAllowed); 823 } catch (RemoteException ex) { 824 throw ex.rethrowFromSystemServer(); 825 } 826 } 827 828 /** 829 * Returns whether or not the user-disabled HDR types are returned from 830 * {@link Display#getHdrCapabilities}. 831 */ areUserDisabledHdrTypesAllowed()832 public boolean areUserDisabledHdrTypesAllowed() { 833 try { 834 return mDm.areUserDisabledHdrTypesAllowed(); 835 } catch (RemoteException ex) { 836 throw ex.rethrowFromSystemServer(); 837 } 838 } 839 840 /** 841 * Returns the HDR formats disabled by the user. 842 * 843 */ getUserDisabledHdrTypes()844 public int[] getUserDisabledHdrTypes() { 845 try { 846 return mDm.getUserDisabledHdrTypes(); 847 } catch (RemoteException ex) { 848 throw ex.rethrowFromSystemServer(); 849 } 850 } 851 852 /** 853 * Resets the implicit registration of refresh rate change callbacks 854 * 855 */ resetImplicitRefreshRateCallbackStatus()856 public void resetImplicitRefreshRateCallbackStatus() { 857 if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) { 858 synchronized (mLock) { 859 mShouldImplicitlyRegisterRrChanges = false; 860 } 861 } 862 } 863 864 /** 865 * Overrides HDR modes for a display device. 866 * 867 */ 868 @RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER) overrideHdrTypes(int displayId, int[] modes)869 public void overrideHdrTypes(int displayId, int[] modes) { 870 try { 871 mDm.overrideHdrTypes(displayId, modes); 872 } catch (RemoteException ex) { 873 throw ex.rethrowFromSystemServer(); 874 } 875 } 876 877 requestColorMode(int displayId, int colorMode)878 public void requestColorMode(int displayId, int colorMode) { 879 try { 880 mDm.requestColorMode(displayId, colorMode); 881 } catch (RemoteException ex) { 882 throw ex.rethrowFromSystemServer(); 883 } 884 } 885 createVirtualDisplay(@onNull Context context, MediaProjection projection, @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback, @Nullable Executor executor)886 public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection, 887 @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback, 888 @Nullable Executor executor) { 889 VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, executor); 890 IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; 891 int displayId; 892 try { 893 displayId = mDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper, 894 projectionToken, context.getPackageName()); 895 } catch (RemoteException ex) { 896 throw ex.rethrowFromSystemServer(); 897 } 898 return createVirtualDisplayWrapper(virtualDisplayConfig, callbackWrapper, 899 displayId); 900 } 901 902 /** 903 * Create a VirtualDisplay wrapper object for a newly created virtual display ; to be called 904 * once the display has been created in system_server. 905 */ 906 @Nullable createVirtualDisplayWrapper(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callbackWrapper, int displayId)907 public VirtualDisplay createVirtualDisplayWrapper(VirtualDisplayConfig virtualDisplayConfig, 908 IVirtualDisplayCallback callbackWrapper, int displayId) { 909 if (displayId < 0) { 910 Log.e(TAG, "Could not create virtual display: " + virtualDisplayConfig.getName()); 911 return null; 912 } 913 Display display = getRealDisplay(displayId); 914 if (display == null) { 915 Log.wtf(TAG, "Could not obtain display info for newly created " 916 + "virtual display: " + virtualDisplayConfig.getName()); 917 try { 918 mDm.releaseVirtualDisplay(callbackWrapper); 919 } catch (RemoteException ex) { 920 throw ex.rethrowFromSystemServer(); 921 } 922 return null; 923 } 924 return new VirtualDisplay(this, display, callbackWrapper, 925 virtualDisplayConfig.getSurface()); 926 } 927 setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface)928 public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) { 929 try { 930 mDm.setVirtualDisplaySurface(token, surface); 931 } catch (RemoteException ex) { 932 throw ex.rethrowFromSystemServer(); 933 } 934 } 935 resizeVirtualDisplay(IVirtualDisplayCallback token, int width, int height, int densityDpi)936 public void resizeVirtualDisplay(IVirtualDisplayCallback token, 937 int width, int height, int densityDpi) { 938 try { 939 mDm.resizeVirtualDisplay(token, width, height, densityDpi); 940 } catch (RemoteException ex) { 941 throw ex.rethrowFromSystemServer(); 942 } 943 } 944 releaseVirtualDisplay(IVirtualDisplayCallback token)945 public void releaseVirtualDisplay(IVirtualDisplayCallback token) { 946 try { 947 mDm.releaseVirtualDisplay(token); 948 } catch (RemoteException ex) { 949 throw ex.rethrowFromSystemServer(); 950 } 951 } 952 setVirtualDisplayRotation(IVirtualDisplayCallback token, @Surface.Rotation int rotation)953 void setVirtualDisplayRotation(IVirtualDisplayCallback token, @Surface.Rotation int rotation) { 954 try { 955 mDm.setVirtualDisplayRotation(token, rotation); 956 } catch (RemoteException ex) { 957 throw ex.rethrowFromSystemServer(); 958 } 959 } 960 961 /** 962 * Gets the stable device display size, in pixels. 963 */ getStableDisplaySize()964 public Point getStableDisplaySize() { 965 try { 966 return mDm.getStableDisplaySize(); 967 } catch (RemoteException ex) { 968 throw ex.rethrowFromSystemServer(); 969 } 970 } 971 972 /** 973 * Retrieves brightness change events. 974 */ getBrightnessEvents(String callingPackage)975 public List<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) { 976 try { 977 ParceledListSlice<BrightnessChangeEvent> events = 978 mDm.getBrightnessEvents(callingPackage); 979 if (events == null) { 980 return Collections.emptyList(); 981 } 982 return events.getList(); 983 } catch (RemoteException ex) { 984 throw ex.rethrowFromSystemServer(); 985 } 986 } 987 988 /** 989 * Retrieves Brightness Info for the specified display. 990 */ getBrightnessInfo(int displayId)991 public BrightnessInfo getBrightnessInfo(int displayId) { 992 try { 993 return mDm.getBrightnessInfo(displayId); 994 } catch (RemoteException ex) { 995 throw ex.rethrowFromSystemServer(); 996 } 997 } 998 999 /** 1000 * Gets the preferred wide gamut color space for all displays. 1001 * The wide gamut color space is returned from composition pipeline 1002 * based on hardware capability. 1003 * 1004 * @hide 1005 */ getPreferredWideGamutColorSpace()1006 public ColorSpace getPreferredWideGamutColorSpace() { 1007 return mWideColorSpace; 1008 } 1009 1010 /** 1011 * Gets the overlay properties for all displays. 1012 * 1013 * @hide 1014 */ getOverlaySupport()1015 public OverlayProperties getOverlaySupport() { 1016 return mOverlayProperties; 1017 } 1018 1019 /** 1020 * Sets the global brightness configuration for a given user. 1021 * 1022 * @hide 1023 */ setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId, String packageName)1024 public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId, 1025 String packageName) { 1026 try { 1027 mDm.setBrightnessConfigurationForUser(c, userId, packageName); 1028 } catch (RemoteException ex) { 1029 throw ex.rethrowFromSystemServer(); 1030 } 1031 } 1032 1033 /** 1034 * Sets the brightness configuration for a given display. 1035 * 1036 * @hide 1037 */ setBrightnessConfigurationForDisplay(BrightnessConfiguration c, String uniqueDisplayId, int userId, String packageName)1038 public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c, 1039 String uniqueDisplayId, int userId, String packageName) { 1040 try { 1041 mDm.setBrightnessConfigurationForDisplay(c, uniqueDisplayId, userId, packageName); 1042 } catch (RemoteException ex) { 1043 throw ex.rethrowFromSystemServer(); 1044 } 1045 } 1046 1047 /** 1048 * Gets the brightness configuration for a given display or null if one hasn't been set. 1049 * 1050 * @hide 1051 */ getBrightnessConfigurationForDisplay(String uniqueDisplayId, int userId)1052 public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueDisplayId, 1053 int userId) { 1054 try { 1055 return mDm.getBrightnessConfigurationForDisplay(uniqueDisplayId, userId); 1056 } catch (RemoteException ex) { 1057 throw ex.rethrowFromSystemServer(); 1058 } 1059 } 1060 1061 /** 1062 * Gets the global brightness configuration for a given user or null if one hasn't been set. 1063 * 1064 * @hide 1065 */ getBrightnessConfigurationForUser(int userId)1066 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { 1067 try { 1068 return mDm.getBrightnessConfigurationForUser(userId); 1069 } catch (RemoteException ex) { 1070 throw ex.rethrowFromSystemServer(); 1071 } 1072 } 1073 1074 /** 1075 * Gets the default brightness configuration or null if one hasn't been configured. 1076 * 1077 * @hide 1078 */ getDefaultBrightnessConfiguration()1079 public BrightnessConfiguration getDefaultBrightnessConfiguration() { 1080 try { 1081 return mDm.getDefaultBrightnessConfiguration(); 1082 } catch (RemoteException ex) { 1083 throw ex.rethrowFromSystemServer(); 1084 } 1085 } 1086 1087 /** 1088 * Gets the last requested minimal post processing setting for the display with displayId. 1089 * 1090 * @hide 1091 */ isMinimalPostProcessingRequested(int displayId)1092 public boolean isMinimalPostProcessingRequested(int displayId) { 1093 try { 1094 return mDm.isMinimalPostProcessingRequested(displayId); 1095 } catch (RemoteException ex) { 1096 throw ex.rethrowFromSystemServer(); 1097 } 1098 } 1099 1100 /** 1101 * Temporarily sets the brightness of the display. 1102 * <p> 1103 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. 1104 * </p> 1105 * 1106 * @param brightness The brightness value from 0.0f to 1.0f. 1107 * 1108 * @hide Requires signature permission. 1109 */ setTemporaryBrightness(int displayId, float brightness)1110 public void setTemporaryBrightness(int displayId, float brightness) { 1111 try { 1112 mDm.setTemporaryBrightness(displayId, brightness); 1113 } catch (RemoteException ex) { 1114 throw ex.rethrowFromSystemServer(); 1115 } 1116 } 1117 1118 1119 /** 1120 * Sets the brightness of the display. 1121 * 1122 * @param brightness The brightness value from 0.0f to 1.0f. 1123 * 1124 * @hide 1125 */ setBrightness(int displayId, float brightness)1126 public void setBrightness(int displayId, float brightness) { 1127 try { 1128 mDm.setBrightness(displayId, brightness); 1129 } catch (RemoteException ex) { 1130 throw ex.rethrowFromSystemServer(); 1131 } 1132 } 1133 1134 /** 1135 * Report whether/how the display supports DISPLAY_DECORATION. 1136 * 1137 * @param displayId The display whose support is being queried. 1138 * 1139 * @hide 1140 */ getDisplayDecorationSupport(int displayId)1141 public DisplayDecorationSupport getDisplayDecorationSupport(int displayId) { 1142 try { 1143 return mDm.getDisplayDecorationSupport(displayId); 1144 } catch (RemoteException ex) { 1145 throw ex.rethrowFromSystemServer(); 1146 } 1147 } 1148 1149 /** 1150 * Gets the brightness of the display. 1151 * 1152 * @param displayId The display from which to get the brightness 1153 * 1154 * @hide 1155 */ getBrightness(int displayId)1156 public float getBrightness(int displayId) { 1157 try { 1158 return mDm.getBrightness(displayId); 1159 } catch (RemoteException ex) { 1160 throw ex.rethrowFromSystemServer(); 1161 } 1162 } 1163 1164 /** 1165 * Temporarily sets the auto brightness adjustment factor. 1166 * <p> 1167 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. 1168 * </p> 1169 * 1170 * @param adjustment The adjustment factor from -1.0 to 1.0. 1171 * 1172 * @hide Requires signature permission. 1173 */ setTemporaryAutoBrightnessAdjustment(float adjustment)1174 public void setTemporaryAutoBrightnessAdjustment(float adjustment) { 1175 try { 1176 mDm.setTemporaryAutoBrightnessAdjustment(adjustment); 1177 } catch (RemoteException ex) { 1178 throw ex.rethrowFromSystemServer(); 1179 } 1180 } 1181 1182 /** 1183 * Returns the minimum brightness curve, which guarantess that any brightness curve that dips 1184 * below it is rejected by the system. 1185 * This prevent auto-brightness from setting the screen so dark as to prevent the user from 1186 * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable 1187 * in that ambient brightness. 1188 * 1189 * @return The minimum brightness curve (as lux values and their corresponding nits values). 1190 */ getMinimumBrightnessCurve()1191 public Pair<float[], float[]> getMinimumBrightnessCurve() { 1192 try { 1193 Curve curve = mDm.getMinimumBrightnessCurve(); 1194 return Pair.create(curve.getX(), curve.getY()); 1195 } catch (RemoteException ex) { 1196 throw ex.rethrowFromSystemServer(); 1197 } 1198 } 1199 1200 /** 1201 * Retrieves ambient brightness stats. 1202 */ getAmbientBrightnessStats()1203 public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() { 1204 try { 1205 ParceledListSlice<AmbientBrightnessDayStats> stats = mDm.getAmbientBrightnessStats(); 1206 if (stats == null) { 1207 return Collections.emptyList(); 1208 } 1209 return stats.getList(); 1210 } catch (RemoteException ex) { 1211 throw ex.rethrowFromSystemServer(); 1212 } 1213 } 1214 1215 /** 1216 * Sets the default display mode, according to the refresh rate and the resolution chosen by the 1217 * user. 1218 */ setUserPreferredDisplayMode(int displayId, Display.Mode mode)1219 public void setUserPreferredDisplayMode(int displayId, Display.Mode mode) { 1220 try { 1221 mDm.setUserPreferredDisplayMode(displayId, mode); 1222 } catch (RemoteException ex) { 1223 throw ex.rethrowFromSystemServer(); 1224 } 1225 } 1226 1227 /** 1228 * Returns the user preferred display mode. 1229 */ getUserPreferredDisplayMode(int displayId)1230 public Display.Mode getUserPreferredDisplayMode(int displayId) { 1231 try { 1232 return mDm.getUserPreferredDisplayMode(displayId); 1233 } catch (RemoteException ex) { 1234 throw ex.rethrowFromSystemServer(); 1235 } 1236 } 1237 1238 /** 1239 * Returns the system preferred display mode. 1240 */ getSystemPreferredDisplayMode(int displayId)1241 public Display.Mode getSystemPreferredDisplayMode(int displayId) { 1242 try { 1243 return mDm.getSystemPreferredDisplayMode(displayId); 1244 } catch (RemoteException ex) { 1245 throw ex.rethrowFromSystemServer(); 1246 } 1247 } 1248 1249 /** 1250 * Sets the {@link HdrConversionMode} for the device. 1251 */ setHdrConversionMode(@onNull HdrConversionMode hdrConversionMode)1252 public void setHdrConversionMode(@NonNull HdrConversionMode hdrConversionMode) { 1253 try { 1254 mDm.setHdrConversionMode(hdrConversionMode); 1255 } catch (RemoteException ex) { 1256 throw ex.rethrowFromSystemServer(); 1257 } 1258 } 1259 1260 /** 1261 * Returns the {@link HdrConversionMode} of the device, which is set by the user. 1262 * The HDR conversion mode chosen by user is returned irrespective of whether HDR conversion 1263 * is disabled by an app. 1264 */ getHdrConversionModeSetting()1265 public HdrConversionMode getHdrConversionModeSetting() { 1266 try { 1267 return mDm.getHdrConversionModeSetting(); 1268 } catch (RemoteException ex) { 1269 throw ex.rethrowFromSystemServer(); 1270 } 1271 } 1272 1273 /** 1274 * Returns the {@link HdrConversionMode} of the device. 1275 */ getHdrConversionMode()1276 public HdrConversionMode getHdrConversionMode() { 1277 try { 1278 return mDm.getHdrConversionMode(); 1279 } catch (RemoteException ex) { 1280 throw ex.rethrowFromSystemServer(); 1281 } 1282 } 1283 1284 /** 1285 * Returns the HDR output types supported by the device. 1286 */ getSupportedHdrOutputTypes()1287 public @HdrType int[] getSupportedHdrOutputTypes() { 1288 try { 1289 return mDm.getSupportedHdrOutputTypes(); 1290 } catch (RemoteException ex) { 1291 throw ex.rethrowFromSystemServer(); 1292 } 1293 } 1294 1295 /** 1296 * When enabled the app requested display resolution and refresh rate is always selected 1297 * in DisplayModeDirector regardless of user settings and policies for low brightness, low 1298 * battery etc. 1299 */ setShouldAlwaysRespectAppRequestedMode(boolean enabled)1300 public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { 1301 try { 1302 mDm.setShouldAlwaysRespectAppRequestedMode(enabled); 1303 } catch (RemoteException ex) { 1304 throw ex.rethrowFromSystemServer(); 1305 } 1306 } 1307 1308 /** 1309 * Returns whether DisplayModeDirector is running in a mode which always selects the app 1310 * requested display mode and ignores user settings and policies for low brightness, low 1311 * battery etc. 1312 */ shouldAlwaysRespectAppRequestedMode()1313 public boolean shouldAlwaysRespectAppRequestedMode() { 1314 try { 1315 return mDm.shouldAlwaysRespectAppRequestedMode(); 1316 } catch (RemoteException ex) { 1317 throw ex.rethrowFromSystemServer(); 1318 } 1319 } 1320 1321 /** 1322 * Sets the refresh rate switching type. 1323 * 1324 * @hide 1325 */ setRefreshRateSwitchingType(@isplayManager.SwitchingType int newValue)1326 public void setRefreshRateSwitchingType(@DisplayManager.SwitchingType int newValue) { 1327 try { 1328 mDm.setRefreshRateSwitchingType(newValue); 1329 } catch (RemoteException ex) { 1330 throw ex.rethrowFromSystemServer(); 1331 } 1332 } 1333 1334 /** 1335 * Returns the refresh rate switching type. 1336 * 1337 * @hide 1338 */ 1339 @DisplayManager.SwitchingType getRefreshRateSwitchingType()1340 public int getRefreshRateSwitchingType() { 1341 try { 1342 return mDm.getRefreshRateSwitchingType(); 1343 } catch (RemoteException ex) { 1344 throw ex.rethrowFromSystemServer(); 1345 } 1346 } 1347 1348 /** 1349 * Sets allowed display mode ids 1350 * 1351 * @hide 1352 */ 1353 @RequiresPermission("android.permission.RESTRICT_DISPLAY_MODES") requestDisplayModes(int displayId, @Nullable int[] modeIds)1354 public void requestDisplayModes(int displayId, @Nullable int[] modeIds) { 1355 try { 1356 mDm.requestDisplayModes(mToken, displayId, modeIds); 1357 } catch (RemoteException ex) { 1358 throw ex.rethrowFromSystemServer(); 1359 } 1360 } 1361 1362 /** 1363 * @param displayId The ID of the display 1364 * @return The highest HDR/SDR ratio of the ratios defined in Display Device Config. If no 1365 * HDR/SDR map is defined, this always returns 1. 1366 */ 1367 @FlaggedApi(com.android.server.display.feature.flags.Flags.FLAG_HIGHEST_HDR_SDR_RATIO_API) getHighestHdrSdrRatio(int displayId)1368 public float getHighestHdrSdrRatio(int displayId) { 1369 try { 1370 return mDm.getHighestHdrSdrRatio(displayId); 1371 } catch (RemoteException ex) { 1372 throw ex.rethrowFromSystemServer(); 1373 } 1374 } 1375 1376 /** 1377 * @see DisplayManager#getDozeBrightnessSensorValueToBrightness 1378 */ 1379 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 1380 @Nullable getDozeBrightnessSensorValueToBrightness(int displayId)1381 public float[] getDozeBrightnessSensorValueToBrightness(int displayId) { 1382 try { 1383 return mDm.getDozeBrightnessSensorValueToBrightness(displayId); 1384 } catch (RemoteException ex) { 1385 throw ex.rethrowFromSystemServer(); 1386 } 1387 } 1388 1389 /** 1390 * @see DisplayManager#getDefaultDozeBrightness 1391 */ 1392 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 1393 @FloatRange(from = 0f, to = 1f) getDefaultDozeBrightness(int displayId)1394 public float getDefaultDozeBrightness(int displayId) { 1395 try { 1396 return mDm.getDefaultDozeBrightness(displayId); 1397 } catch (RemoteException ex) { 1398 throw ex.rethrowFromSystemServer(); 1399 } 1400 } 1401 1402 /** 1403 * @see DisplayManager#getDisplayTopology 1404 */ 1405 @RequiresPermission(MANAGE_DISPLAYS) 1406 @Nullable getDisplayTopology()1407 public DisplayTopology getDisplayTopology() { 1408 try { 1409 return mDm.getDisplayTopology(); 1410 } catch (RemoteException ex) { 1411 throw ex.rethrowFromSystemServer(); 1412 } 1413 } 1414 1415 /** 1416 * @see DisplayManager#setDisplayTopology 1417 */ 1418 @RequiresPermission(MANAGE_DISPLAYS) setDisplayTopology(DisplayTopology topology)1419 public void setDisplayTopology(DisplayTopology topology) { 1420 if (topology == null) { 1421 throw new IllegalArgumentException("Topology must not be null"); 1422 } 1423 try { 1424 mDm.setDisplayTopology(topology); 1425 } catch (RemoteException ex) { 1426 throw ex.rethrowFromSystemServer(); 1427 } 1428 } 1429 1430 /** 1431 * @see DisplayManager#registerTopologyListener 1432 */ 1433 @RequiresPermission(MANAGE_DISPLAYS) registerTopologyListener(@onNull @allbackExecutor Executor executor, @NonNull Consumer<DisplayTopology> listener, String packageName)1434 public void registerTopologyListener(@NonNull @CallbackExecutor Executor executor, 1435 @NonNull Consumer<DisplayTopology> listener, String packageName) { 1436 if (!Flags.displayTopology()) { 1437 return; 1438 } 1439 if (listener == null) { 1440 throw new IllegalArgumentException("listener must not be null"); 1441 } 1442 if (extraLogging()) { 1443 Slog.i(TAG, "Registering display topology listener: packageName=" + packageName); 1444 } 1445 synchronized (mLock) { 1446 DisplayTopologyListenerDelegate delegate = findTopologyListenerLocked(listener); 1447 if (delegate == null) { 1448 mTopologyListeners.add(new DisplayTopologyListenerDelegate(listener, executor, 1449 packageName)); 1450 registerCallbackIfNeededLocked(); 1451 updateCallbackIfNeededLocked(); 1452 } 1453 maybeLogAllTopologyListeners(); 1454 } 1455 } 1456 1457 /** 1458 * @see DisplayManager#unregisterTopologyListener 1459 */ 1460 @RequiresPermission(MANAGE_DISPLAYS) unregisterTopologyListener(@onNull Consumer<DisplayTopology> listener)1461 public void unregisterTopologyListener(@NonNull Consumer<DisplayTopology> listener) { 1462 if (!Flags.displayTopology()) { 1463 return; 1464 } 1465 if (listener == null) { 1466 throw new IllegalArgumentException("listener must not be null"); 1467 } 1468 if (extraLogging()) { 1469 Slog.i(TAG, "Unregistering display topology listener: " + listener); 1470 } 1471 synchronized (mLock) { 1472 DisplayTopologyListenerDelegate delegate = findTopologyListenerLocked(listener); 1473 if (delegate != null) { 1474 mTopologyListeners.remove(delegate); 1475 updateCallbackIfNeededLocked(); 1476 } 1477 } 1478 maybeLogAllTopologyListeners(); 1479 } 1480 1481 private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { 1482 @Override onDisplayEvent(int displayId, @DisplayEvent int event)1483 public void onDisplayEvent(int displayId, @DisplayEvent int event) { 1484 if (DEBUG) { 1485 Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" 1486 + eventToString(event)); 1487 } 1488 handleDisplayEvent(displayId, event, false /* forceUpdate */); 1489 } 1490 1491 @Override onTopologyChanged(DisplayTopology topology)1492 public void onTopologyChanged(DisplayTopology topology) { 1493 if (DEBUG) { 1494 Log.d(TAG, "onTopologyChanged: " + topology); 1495 } 1496 for (DisplayTopologyListenerDelegate listener : mTopologyListeners) { 1497 listener.onTopologyChanged(topology); 1498 } 1499 } 1500 } 1501 1502 @VisibleForTesting 1503 public static final class DisplayListenerDelegate { 1504 public final DisplayListener mListener; 1505 public volatile long mInternalEventFlagsMask; 1506 1507 // Indicates if the client explicitly supplied the display events to be subscribed to. 1508 private final boolean mIsEventFilterExplicit; 1509 1510 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 1511 private final Executor mExecutor; 1512 private AtomicLong mGenerationId = new AtomicLong(1); 1513 private final String mPackageName; 1514 DisplayListenerDelegate(DisplayListener listener, @NonNull Executor executor, @InternalEventFlag long internalEventFlag, String packageName, boolean isEventFilterExplicit)1515 DisplayListenerDelegate(DisplayListener listener, @NonNull Executor executor, 1516 @InternalEventFlag long internalEventFlag, String packageName, 1517 boolean isEventFilterExplicit) { 1518 mExecutor = executor; 1519 mListener = listener; 1520 mInternalEventFlagsMask = internalEventFlag; 1521 mPackageName = packageName; 1522 mIsEventFilterExplicit = isEventFilterExplicit; 1523 } 1524 sendDisplayEvent(int displayId, @DisplayEvent int event, @Nullable DisplayInfo info, boolean forceUpdate)1525 void sendDisplayEvent(int displayId, @DisplayEvent int event, @Nullable DisplayInfo info, 1526 boolean forceUpdate) { 1527 if (extraLogging()) { 1528 Slog.i(TAG, "Sending Display Event: " + eventToString(event)); 1529 } 1530 long generationId = mGenerationId.get(); 1531 mExecutor.execute(() -> { 1532 // If the generation id's don't match we were canceled 1533 if (generationId == mGenerationId.get()) { 1534 handleDisplayEventInner(displayId, event, info, forceUpdate); 1535 } 1536 }); 1537 } 1538 1539 @VisibleForTesting isEventFilterExplicit()1540 public boolean isEventFilterExplicit() { 1541 return mIsEventFilterExplicit; 1542 } 1543 clearEvents()1544 void clearEvents() { 1545 mGenerationId.incrementAndGet(); 1546 } 1547 setEventsMask(@nternalEventFlag long newInternalEventFlagsMask)1548 void setEventsMask(@InternalEventFlag long newInternalEventFlagsMask) { 1549 mInternalEventFlagsMask = newInternalEventFlagsMask; 1550 } 1551 implicitlyRegisterForRRChanges()1552 private void implicitlyRegisterForRRChanges() { 1553 // For backward compatibility, if the user didn't supply the explicit events while 1554 // subscribing, register them to refresh rate change events if they subscribed to 1555 // display changed events 1556 if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED) != 0 1557 && !mIsEventFilterExplicit) { 1558 setEventsMask(mInternalEventFlagsMask 1559 | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE); 1560 } 1561 } 1562 handleDisplayEventInner(int displayId, @DisplayEvent int event, @Nullable DisplayInfo info, boolean forceUpdate)1563 private void handleDisplayEventInner(int displayId, @DisplayEvent int event, 1564 @Nullable DisplayInfo info, boolean forceUpdate) { 1565 if (extraLogging()) { 1566 Slog.i(TAG, "DLD(" + eventToString(event) 1567 + ", display=" + displayId 1568 + ", mEventsMask=" + Long.toBinaryString(mInternalEventFlagsMask) 1569 + ", mPackageName=" + mPackageName 1570 + ", displayInfo=" + info 1571 + ", listener=" + mListener.getClass() + ")"); 1572 } 1573 if (DEBUG) { 1574 Trace.beginSection( 1575 TextUtils.trimToSize( 1576 "DLD(" + eventToString(event) 1577 + ", display=" + displayId 1578 + ", listener=" + mListener.getClass() + ")", 127)); 1579 } 1580 switch (event) { 1581 case EVENT_DISPLAY_ADDED: 1582 if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_ADDED) != 0) { 1583 mListener.onDisplayAdded(displayId); 1584 } 1585 break; 1586 case EVENT_DISPLAY_BASIC_CHANGED: 1587 if ((mInternalEventFlagsMask 1588 & INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED) != 0) { 1589 if (info != null && (forceUpdate || !info.equals(mDisplayInfo))) { 1590 if (extraLogging()) { 1591 Slog.i(TAG, "Sending onDisplayChanged: Display Changed. Info: " 1592 + info); 1593 } 1594 mDisplayInfo.copyFrom(info); 1595 mListener.onDisplayChanged(displayId); 1596 } 1597 } 1598 break; 1599 case EVENT_DISPLAY_BRIGHTNESS_CHANGED: 1600 if ((mInternalEventFlagsMask 1601 & INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED) != 0) { 1602 mListener.onDisplayChanged(displayId); 1603 } 1604 break; 1605 case EVENT_DISPLAY_REMOVED: 1606 if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_REMOVED) 1607 != 0) { 1608 mListener.onDisplayRemoved(displayId); 1609 } 1610 break; 1611 case EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED: 1612 if ((mInternalEventFlagsMask 1613 & INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED) != 0) { 1614 mListener.onDisplayChanged(displayId); 1615 } 1616 break; 1617 case EVENT_DISPLAY_CONNECTED: 1618 if ((mInternalEventFlagsMask 1619 & INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) { 1620 mListener.onDisplayConnected(displayId); 1621 } 1622 break; 1623 case EVENT_DISPLAY_DISCONNECTED: 1624 if ((mInternalEventFlagsMask 1625 & INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) { 1626 mListener.onDisplayDisconnected(displayId); 1627 } 1628 break; 1629 case EVENT_DISPLAY_REFRESH_RATE_CHANGED: 1630 if ((mInternalEventFlagsMask 1631 & INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) { 1632 mListener.onDisplayChanged(displayId); 1633 } 1634 break; 1635 case EVENT_DISPLAY_STATE_CHANGED: 1636 if ((mInternalEventFlagsMask 1637 & INTERNAL_EVENT_FLAG_DISPLAY_STATE) != 0) { 1638 mListener.onDisplayChanged(displayId); 1639 } 1640 break; 1641 case EVENT_DISPLAY_COMMITTED_STATE_CHANGED: 1642 if ((mInternalEventFlagsMask 1643 & INTERNAL_EVENT_FLAG_DISPLAY_COMMITTED_STATE_CHANGED) != 0) { 1644 mListener.onDisplayChanged(displayId); 1645 } 1646 break; 1647 } 1648 if (DEBUG) { 1649 Trace.endSection(); 1650 } 1651 } 1652 1653 @Override toString()1654 public String toString() { 1655 return "flag: {" + mInternalEventFlagsMask + "}, for " + mListener.getClass(); 1656 } 1657 } 1658 1659 /** 1660 * Assists in dispatching VirtualDisplay lifecycle event callbacks on a given Executor. 1661 */ 1662 public static final class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub { 1663 @Nullable private final VirtualDisplay.Callback mCallback; 1664 @Nullable private final Executor mExecutor; 1665 1666 /** 1667 * Creates a virtual display callback. 1668 * 1669 * @param callback The callback to call for virtual display events, or {@code null} if the 1670 * caller does not wish to receive callback events. 1671 * @param executor The executor to call the {@code callback} on. Must not be {@code null} if 1672 * the callback is not {@code null}. 1673 */ VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor)1674 public VirtualDisplayCallback(VirtualDisplay.Callback callback, Executor executor) { 1675 mCallback = callback; 1676 mExecutor = mCallback != null ? Objects.requireNonNull(executor) : null; 1677 } 1678 1679 // These methods are called from the binder thread, but the AIDL is oneway, so it should be 1680 // safe to call the callback on arbitrary executors directly without risking blocking 1681 // the system. 1682 1683 @Override // Binder call onPaused()1684 public void onPaused() { 1685 if (mCallback != null) { 1686 mExecutor.execute(mCallback::onPaused); 1687 } 1688 } 1689 1690 @Override // Binder call onResumed()1691 public void onResumed() { 1692 if (mCallback != null) { 1693 mExecutor.execute(mCallback::onResumed); 1694 } 1695 } 1696 1697 @Override // Binder call onStopped()1698 public void onStopped() { 1699 if (mCallback != null) { 1700 mExecutor.execute(mCallback::onStopped); 1701 } 1702 } 1703 } 1704 1705 private static final class DisplayTopologyListenerDelegate { 1706 private final Consumer<DisplayTopology> mListener; 1707 private final Executor mExecutor; 1708 private final String mPackageName; 1709 DisplayTopologyListenerDelegate(@onNull Consumer<DisplayTopology> listener, @NonNull @CallbackExecutor Executor executor, String packageName)1710 DisplayTopologyListenerDelegate(@NonNull Consumer<DisplayTopology> listener, 1711 @NonNull @CallbackExecutor Executor executor, String packageName) { 1712 mExecutor = executor; 1713 mListener = listener; 1714 mPackageName = packageName; 1715 } 1716 1717 @Override toString()1718 public String toString() { 1719 return "DisplayTopologyListener {packageName=" + mPackageName + "}"; 1720 } 1721 onTopologyChanged(DisplayTopology topology)1722 void onTopologyChanged(DisplayTopology topology) { 1723 if (extraLogging()) { 1724 Slog.i(TAG, "Sending topology update: " + topology); 1725 } 1726 mExecutor.execute(() -> mListener.accept(topology)); 1727 } 1728 } 1729 1730 /** 1731 * The API portion of the key that identifies the unique PropertyInvalidatedCache token which 1732 * changes every time we update the system's display configuration. 1733 */ 1734 private static final String CACHE_KEY_DISPLAY_INFO_API = "display_info"; 1735 1736 /** 1737 * Invalidates the contents of the display info cache for all applications. Can only 1738 * be called by system_server. 1739 */ invalidateLocalDisplayInfoCaches()1740 public static void invalidateLocalDisplayInfoCaches() { 1741 PropertyInvalidatedCache.invalidateCache(MODULE_SYSTEM, CACHE_KEY_DISPLAY_INFO_API); 1742 } 1743 1744 /** 1745 * Disables the binder call cache. 1746 */ disableLocalDisplayInfoCaches()1747 public void disableLocalDisplayInfoCaches() { 1748 mDisplayCache = null; 1749 } 1750 nSignalNativeCallbacks(float refreshRate)1751 private static native void nSignalNativeCallbacks(float refreshRate); 1752 1753 /** 1754 * Called from AChoreographer via JNI. 1755 * Registers AChoreographer so that refresh rate callbacks can be dispatched from DMS. 1756 * Public for unit testing to be able to call this method. 1757 */ 1758 @VisibleForTesting registerNativeChoreographerForRefreshRateCallbacks()1759 public void registerNativeChoreographerForRefreshRateCallbacks() { 1760 synchronized (mLock) { 1761 mDispatchNativeCallbacks = true; 1762 if (Flags.delayImplicitRrRegistrationUntilRrAccessed()) { 1763 if (!mShouldImplicitlyRegisterRrChanges) { 1764 Slog.i(TAG, "Choreographer implicitly registered for the refresh rate."); 1765 } 1766 mShouldImplicitlyRegisterRrChanges = true; 1767 } 1768 registerCallbackIfNeededLocked(); 1769 updateCallbackIfNeededLocked(); 1770 DisplayInfo display = getDisplayInfoLocked(Display.DEFAULT_DISPLAY); 1771 if (display != null) { 1772 // We need to tell AChoreographer instances the current refresh rate so that apps 1773 // can get it for free once a callback first registers. 1774 mNativeCallbackReportedRefreshRate = display.getRefreshRate(); 1775 nSignalNativeCallbacks(mNativeCallbackReportedRefreshRate); 1776 } 1777 } 1778 } 1779 1780 /** 1781 * Called from AChoreographer via JNI. 1782 * Unregisters AChoreographer from receiving refresh rate callbacks. 1783 * Public for unit testing to be able to call this method. 1784 */ 1785 @VisibleForTesting unregisterNativeChoreographerForRefreshRateCallbacks()1786 public void unregisterNativeChoreographerForRefreshRateCallbacks() { 1787 synchronized (mLock) { 1788 mDispatchNativeCallbacks = false; 1789 updateCallbackIfNeededLocked(); 1790 } 1791 } 1792 eventToString(@isplayEvent int event)1793 private static String eventToString(@DisplayEvent int event) { 1794 switch (event) { 1795 case EVENT_DISPLAY_ADDED: 1796 return "ADDED"; 1797 case EVENT_DISPLAY_BASIC_CHANGED: 1798 return "BASIC_CHANGED"; 1799 case EVENT_DISPLAY_REMOVED: 1800 return "REMOVED"; 1801 case EVENT_DISPLAY_BRIGHTNESS_CHANGED: 1802 return "BRIGHTNESS_CHANGED"; 1803 case EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED: 1804 return "HDR_SDR_RATIO_CHANGED"; 1805 case EVENT_DISPLAY_CONNECTED: 1806 return "EVENT_DISPLAY_CONNECTED"; 1807 case EVENT_DISPLAY_DISCONNECTED: 1808 return "EVENT_DISPLAY_DISCONNECTED"; 1809 case EVENT_DISPLAY_REFRESH_RATE_CHANGED: 1810 return "EVENT_DISPLAY_REFRESH_RATE_CHANGED"; 1811 case EVENT_DISPLAY_STATE_CHANGED: 1812 return "EVENT_DISPLAY_STATE_CHANGED"; 1813 case EVENT_DISPLAY_COMMITTED_STATE_CHANGED: 1814 return "EVENT_DISPLAY_COMMITTED_STATE_CHANGED"; 1815 } 1816 return "UNKNOWN"; 1817 } 1818 1819 initExtraLogging()1820 private static boolean initExtraLogging() { 1821 if (sCurrentPackageName == null) { 1822 sCurrentPackageName = ActivityThread.currentPackageName(); 1823 sExtraDisplayListenerLogging = !TextUtils.isEmpty(EXTRA_LOGGING_PACKAGE_NAME) 1824 && EXTRA_LOGGING_PACKAGE_NAME.equals(sCurrentPackageName); 1825 } 1826 return sExtraDisplayListenerLogging; 1827 } 1828 extraLogging()1829 private static boolean extraLogging() { 1830 return sExtraDisplayListenerLogging; 1831 } 1832 1833 1834 /** 1835 * Maps the supplied public and private event flags to a unified InternalEventFlag 1836 * @param eventFlags A bitmask of the event types for which this listener is subscribed. 1837 * @param privateEventFlags A bitmask of the private event types for which this listener 1838 * is subscribed. 1839 * @return returns the bitmask of both public and private event flags unified to 1840 * InternalEventFlag 1841 */ mapFiltersToInternalEventFlag(@ventType long eventFlags, @DisplayManager.PrivateEventType long privateEventFlags)1842 public @InternalEventFlag long mapFiltersToInternalEventFlag(@EventType long eventFlags, 1843 @DisplayManager.PrivateEventType long privateEventFlags) { 1844 return mapPrivateEventFlags(privateEventFlags) | mapPublicEventFlags(eventFlags); 1845 } 1846 mapPrivateEventFlags(@isplayManager.PrivateEventType long privateEventFlags)1847 private long mapPrivateEventFlags(@DisplayManager.PrivateEventType long privateEventFlags) { 1848 long baseEventMask = 0; 1849 if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS) != 0) { 1850 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED; 1851 } 1852 1853 if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED) != 0) { 1854 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED; 1855 } 1856 1857 if ((privateEventFlags 1858 & DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED) != 0) { 1859 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED; 1860 } 1861 1862 if (Flags.committedStateSeparateEvent()) { 1863 if ((privateEventFlags 1864 & DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_COMMITTED_STATE_CHANGED) != 0) { 1865 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_COMMITTED_STATE_CHANGED; 1866 } 1867 } 1868 return baseEventMask; 1869 } 1870 mapPublicEventFlags(@ventType long eventFlags)1871 private long mapPublicEventFlags(@EventType long eventFlags) { 1872 long baseEventMask = 0; 1873 if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_ADDED) != 0) { 1874 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED; 1875 } 1876 1877 if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_CHANGED) != 0) { 1878 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED; 1879 } 1880 1881 if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_REMOVED) != 0) { 1882 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REMOVED; 1883 } 1884 1885 if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_REFRESH_RATE) != 0) { 1886 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE; 1887 } 1888 1889 if (Flags.displayListenerPerformanceImprovements()) { 1890 if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_STATE) != 0) { 1891 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_STATE; 1892 } 1893 } 1894 1895 return baseEventMask; 1896 } 1897 1898 @VisibleForTesting getDisplayListeners()1899 public CopyOnWriteArrayList<DisplayListenerDelegate> getDisplayListeners() { 1900 return mDisplayListeners; 1901 } 1902 } 1903