• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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