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 com.android.server.display;
18 
19 import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
20 import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT;
21 import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
22 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
23 import static android.hardware.display.DisplayManager.EventsMask;
24 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
25 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
26 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
27 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
28 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
29 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
30 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
31 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
32 import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
33 import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
34 import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
35 import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
36 
37 import android.Manifest;
38 import android.annotation.NonNull;
39 import android.annotation.Nullable;
40 import android.annotation.UserIdInt;
41 import android.app.AppOpsManager;
42 import android.app.compat.CompatChanges;
43 import android.compat.annotation.ChangeId;
44 import android.compat.annotation.EnabledSince;
45 import android.content.Context;
46 import android.content.pm.PackageManager;
47 import android.content.pm.ParceledListSlice;
48 import android.content.res.Resources;
49 import android.content.res.TypedArray;
50 import android.database.ContentObserver;
51 import android.graphics.ColorSpace;
52 import android.graphics.Point;
53 import android.hardware.Sensor;
54 import android.hardware.SensorManager;
55 import android.hardware.devicestate.DeviceStateManager;
56 import android.hardware.display.AmbientBrightnessDayStats;
57 import android.hardware.display.BrightnessChangeEvent;
58 import android.hardware.display.BrightnessConfiguration;
59 import android.hardware.display.BrightnessInfo;
60 import android.hardware.display.Curve;
61 import android.hardware.display.DisplayManager;
62 import android.hardware.display.DisplayManagerGlobal;
63 import android.hardware.display.DisplayManagerInternal;
64 import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
65 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
66 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
67 import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
68 import android.hardware.display.DisplayViewport;
69 import android.hardware.display.DisplayedContentSample;
70 import android.hardware.display.DisplayedContentSamplingAttributes;
71 import android.hardware.display.IDisplayManager;
72 import android.hardware.display.IDisplayManagerCallback;
73 import android.hardware.display.IVirtualDisplayCallback;
74 import android.hardware.display.VirtualDisplayConfig;
75 import android.hardware.display.WifiDisplayStatus;
76 import android.hardware.input.InputManagerInternal;
77 import android.media.projection.IMediaProjection;
78 import android.media.projection.IMediaProjectionManager;
79 import android.net.Uri;
80 import android.os.Binder;
81 import android.os.Handler;
82 import android.os.HandlerExecutor;
83 import android.os.IBinder;
84 import android.os.IBinder.DeathRecipient;
85 import android.os.Looper;
86 import android.os.Message;
87 import android.os.PowerManager;
88 import android.os.Process;
89 import android.os.RemoteException;
90 import android.os.ResultReceiver;
91 import android.os.ServiceManager;
92 import android.os.ShellCallback;
93 import android.os.SystemClock;
94 import android.os.SystemProperties;
95 import android.os.Trace;
96 import android.os.UserHandle;
97 import android.os.UserManager;
98 import android.provider.Settings;
99 import android.sysprop.DisplayProperties;
100 import android.text.TextUtils;
101 import android.util.ArraySet;
102 import android.util.EventLog;
103 import android.util.IntArray;
104 import android.util.Pair;
105 import android.util.Slog;
106 import android.util.SparseArray;
107 import android.util.SparseIntArray;
108 import android.util.Spline;
109 import android.view.Display;
110 import android.view.DisplayEventReceiver;
111 import android.view.DisplayInfo;
112 import android.view.Surface;
113 import android.view.SurfaceControl;
114 
115 import com.android.internal.annotations.GuardedBy;
116 import com.android.internal.annotations.VisibleForTesting;
117 import com.android.internal.display.BrightnessSynchronizer;
118 import com.android.internal.util.DumpUtils;
119 import com.android.internal.util.IndentingPrintWriter;
120 import com.android.server.AnimationThread;
121 import com.android.server.DisplayThread;
122 import com.android.server.LocalServices;
123 import com.android.server.SystemService;
124 import com.android.server.UiThread;
125 import com.android.server.display.DisplayDeviceConfig.SensorData;
126 import com.android.server.display.utils.SensorUtils;
127 import com.android.server.wm.SurfaceAnimationThread;
128 import com.android.server.wm.WindowManagerInternal;
129 
130 import java.io.FileDescriptor;
131 import java.io.PrintWriter;
132 import java.util.ArrayList;
133 import java.util.Arrays;
134 import java.util.List;
135 import java.util.Optional;
136 import java.util.concurrent.CopyOnWriteArrayList;
137 import java.util.concurrent.atomic.AtomicLong;
138 import java.util.function.Consumer;
139 
140 /**
141  * Manages attached displays.
142  * <p>
143  * The {@link DisplayManagerService} manages the global lifecycle of displays,
144  * decides how to configure logical displays based on the physical display devices currently
145  * attached, sends notifications to the system and to applications when the state
146  * changes, and so on.
147  * </p><p>
148  * The display manager service relies on a collection of {@link DisplayAdapter} components,
149  * for discovering and configuring physical display devices attached to the system.
150  * There are separate display adapters for each manner that devices are attached:
151  * one display adapter for physical displays, one for simulated non-functional
152  * displays when the system is headless, one for simulated overlay displays used for
153  * development, one for wifi displays, etc.
154  * </p><p>
155  * Display adapters are only weakly coupled to the display manager service.
156  * Display adapters communicate changes in display device state to the display manager
157  * service asynchronously via a {@link DisplayAdapter.Listener}, and through
158  * the {@link DisplayDeviceRepository.Listener}, which is ultimately registered
159  * by the display manager service.  This separation of concerns is important for
160  * two main reasons.  First, it neatly encapsulates the responsibilities of these
161  * two classes: display adapters handle individual display devices whereas
162  * the display manager service handles the global state.  Second, it eliminates
163  * the potential for deadlocks resulting from asynchronous display device discovery.
164  * </p>
165  *
166  * <h3>Synchronization</h3>
167  * <p>
168  * Because the display manager may be accessed by multiple threads, the synchronization
169  * story gets a little complicated.  In particular, the window manager may call into
170  * the display manager while holding a surface transaction with the expectation that
171  * it can apply changes immediately.  Unfortunately, that means we can't just do
172  * everything asynchronously (*grump*).
173  * </p><p>
174  * To make this work, all of the objects that belong to the display manager must
175  * use the same lock.  We call this lock the synchronization root and it has a unique
176  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
177  * named with the "Locked" suffix.
178  * </p><p>
179  * Where things get tricky is that the display manager is not allowed to make
180  * any potentially reentrant calls, especially into the window manager.  We generally
181  * avoid this by making all potentially reentrant out-calls asynchronous.
182  * </p>
183  */
184 public final class DisplayManagerService extends SystemService {
185     private static final String TAG = "DisplayManagerService";
186     private static final boolean DEBUG = false;
187 
188     // When this system property is set to 0, WFD is forcibly disabled on boot.
189     // When this system property is set to 1, WFD is forcibly enabled on boot.
190     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
191     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
192 
193     private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
194     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
195     // This value needs to be in sync with the threshold
196     // in RefreshRateConfigs::getFrameRateDivider.
197     private static final float THRESHOLD_FOR_REFRESH_RATES_DIVIDERS = 0.0009f;
198 
199     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
200     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
201     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
202     private static final int MSG_REQUEST_TRAVERSAL = 4;
203     private static final int MSG_UPDATE_VIEWPORT = 5;
204     private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6;
205     private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
206     private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
207 
208     private final Context mContext;
209     private final DisplayManagerHandler mHandler;
210     private final Handler mUiHandler;
211     private final DisplayModeDirector mDisplayModeDirector;
212     private WindowManagerInternal mWindowManagerInternal;
213     private InputManagerInternal mInputManagerInternal;
214     private IMediaProjectionManager mProjectionService;
215     private int[] mUserDisabledHdrTypes = {};
216     private boolean mAreUserDisabledHdrTypesAllowed = true;
217 
218     // The synchronization root for the display manager.
219     // This lock guards most of the display manager's state.
220     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
221     // into WindowManagerService methods that require mWindowMap while holding this unless you are
222     // very very sure that no deadlock can occur.
223     private final SyncRoot mSyncRoot = new SyncRoot();
224 
225     // True if in safe mode.
226     // This option may disable certain display adapters.
227     public boolean mSafeMode;
228 
229     // True if we are in a special boot mode where only core applications and
230     // services should be started.  This option may disable certain display adapters.
231     public boolean mOnlyCore;
232 
233     // All callback records indexed by calling process id.
234     public final SparseArray<CallbackRecord> mCallbacks =
235             new SparseArray<CallbackRecord>();
236 
237     // List of all currently registered display adapters.
238     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
239 
240     /**
241      * Repository of all active {@link DisplayDevice}s.
242      */
243     private final DisplayDeviceRepository mDisplayDeviceRepo;
244 
245     /**
246      * Contains all the {@link LogicalDisplay} instances and is responsible for mapping
247      * {@link DisplayDevice}s to {@link LogicalDisplay}s. DisplayManagerService listens to display
248      * event on this object.
249      */
250     private final LogicalDisplayMapper mLogicalDisplayMapper;
251 
252     // List of all display transaction listeners.
253     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
254             new CopyOnWriteArrayList<DisplayTransactionListener>();
255 
256     /** List of all display group listeners. */
257     private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners =
258             new CopyOnWriteArrayList<>();
259 
260     /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
261     private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
262             new SparseArray<>();
263 
264     /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
265     private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
266         // Synchronized to avoid race conditions when updating multiple display states.
267         @Override
268         public synchronized void requestDisplayState(int displayId, int state, float brightness,
269                 float sdrBrightness) {
270             boolean allInactive = true;
271             boolean allOff = true;
272             final boolean stateChanged;
273             synchronized (mSyncRoot) {
274                 final int index = mDisplayStates.indexOfKey(displayId);
275                 if (index > -1) {
276                     final int currentState = mDisplayStates.valueAt(index);
277                     stateChanged = state != currentState;
278                     if (stateChanged) {
279                         final int size = mDisplayStates.size();
280                         for (int i = 0; i < size; i++) {
281                             final int displayState = i == index ? state : mDisplayStates.valueAt(i);
282                             if (displayState != Display.STATE_OFF) {
283                                 allOff = false;
284                             }
285                             if (Display.isActiveState(displayState)) {
286                                 allInactive = false;
287                             }
288                             if (!allOff && !allInactive) {
289                                 break;
290                             }
291                         }
292                     }
293                 } else {
294                     stateChanged = false;
295                 }
296             }
297 
298             // The order of operations is important for legacy reasons.
299             if (state == Display.STATE_OFF) {
300                 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
301             }
302 
303             if (stateChanged) {
304                 mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff);
305             }
306 
307             if (state != Display.STATE_OFF) {
308                 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
309             }
310         }
311     };
312 
313     /**
314      * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display
315      * state.
316      */
317     private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;
318 
319     /** The {@link Handler} used by all {@link DisplayPowerController}s. */
320     private Handler mPowerHandler;
321 
322     // A map from LogicalDisplay ID to display power state.
323     @GuardedBy("mSyncRoot")
324     private final SparseIntArray mDisplayStates = new SparseIntArray();
325 
326     // A map from LogicalDisplay ID to display brightness.
327     @GuardedBy("mSyncRoot")
328     private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>();
329 
330     // Set to true when there are pending display changes that have yet to be applied
331     // to the surface flinger state.
332     private boolean mPendingTraversal;
333 
334     // The Wifi display adapter, or null if not registered.
335     private WifiDisplayAdapter mWifiDisplayAdapter;
336 
337     // The number of active wifi display scan requests.
338     private int mWifiDisplayScanRequestCount;
339 
340     // The virtual display adapter, or null if not registered.
341     private VirtualDisplayAdapter mVirtualDisplayAdapter;
342 
343     // The User ID of the current user
344     private @UserIdInt int mCurrentUserId;
345 
346     // The stable device screen height and width. These are not tied to a specific display, even
347     // the default display, because they need to be stable over the course of the device's entire
348     // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
349     // device).
350     private Point mStableDisplaySize = new Point();
351 
352     // Whether the system has finished booting or not.
353     private boolean mSystemReady;
354 
355     // The top inset of the default display.
356     // This gets persisted so that the boot animation knows how to transition from the display's
357     // full size to the size configured by the user. Right now we only persist and animate the top
358     // inset, but theoretically we could do it for all of them.
359     private int mDefaultDisplayTopInset;
360 
361     // Viewports of the default display and the display that should receive touch
362     // input from an external source.  Used by the input system.
363     @GuardedBy("mSyncRoot")
364     private final ArrayList<DisplayViewport> mViewports = new ArrayList<>();
365 
366     // Persistent data store for all internal settings maintained by the display manager service.
367     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
368 
369     // Temporary callback list, used when sending display events to applications.
370     // May be used outside of the lock but only on the handler thread.
371     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
372 
373     // Temporary viewports, used when sending new viewport information to the
374     // input system.  May be used outside of the lock but only on the handler thread.
375     private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>();
376 
377     // The default color mode for default displays. Overrides the usual
378     // Display.Display.COLOR_MODE_DEFAULT for displays with the
379     // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
380     private final int mDefaultDisplayDefaultColorMode;
381 
382     // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
383     private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
384 
385     private final Injector mInjector;
386 
387     // The minimum brightness curve, which guarantess that any brightness curve that dips below it
388     // is rejected by the system.
389     private final Curve mMinimumBrightnessCurve;
390     private final Spline mMinimumBrightnessSpline;
391     private final ColorSpace mWideColorSpace;
392 
393     private SensorManager mSensorManager;
394     private BrightnessTracker mBrightnessTracker;
395 
396 
397     // Whether minimal post processing is allowed by the user.
398     @GuardedBy("mSyncRoot")
399     private boolean mMinimalPostProcessingAllowed;
400 
401     // Receives notifications about changes to Settings.
402     private SettingsObserver mSettingsObserver;
403 
404     private final boolean mAllowNonNativeRefreshRateOverride;
405 
406     private final BrightnessSynchronizer mBrightnessSynchronizer;
407 
408     /**
409      * Applications use {@link android.view.Display#getRefreshRate} and
410      * {@link android.view.Display.Mode#getRefreshRate} to know what is the display refresh rate.
411      * Starting with Android S, the platform might throttle down applications frame rate to a
412      * divisor of the refresh rate if it is more preferable (for example if the application called
413      * to {@link android.view.Surface#setFrameRate}).
414      * Applications will experience {@link android.view.Choreographer#postFrameCallback} callbacks
415      * and backpressure at the throttled frame rate.
416      *
417      * {@link android.view.Display#getRefreshRate} will always return the application frame rate
418      * and not the physical display refresh rate to allow applications to do frame pacing correctly.
419      *
420      * {@link android.view.Display.Mode#getRefreshRate} will return the application frame rate if
421      * compiled to a previous release and starting with Android S it will return the physical
422      * display refresh rate.
423      */
424     @ChangeId
425     @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
426     static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE = 170503758L;
427 
DisplayManagerService(Context context)428     public DisplayManagerService(Context context) {
429         this(context, new Injector());
430     }
431 
432     @VisibleForTesting
DisplayManagerService(Context context, Injector injector)433     DisplayManagerService(Context context, Injector injector) {
434         super(context);
435         mInjector = injector;
436         mContext = context;
437         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
438         mUiHandler = UiThread.getHandler();
439         mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
440         mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
441                 new LogicalDisplayListener(), mSyncRoot, mHandler);
442         mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
443         mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
444         Resources resources = mContext.getResources();
445         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
446                 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
447         mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);
448         float[] lux = getFloatArray(resources.obtainTypedArray(
449                 com.android.internal.R.array.config_minimumBrightnessCurveLux));
450         float[] nits = getFloatArray(resources.obtainTypedArray(
451                 com.android.internal.R.array.config_minimumBrightnessCurveNits));
452         mMinimumBrightnessCurve = new Curve(lux, nits);
453         mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
454 
455         mCurrentUserId = UserHandle.USER_SYSTEM;
456         ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
457         mWideColorSpace = colorSpaces[1];
458         mAllowNonNativeRefreshRateOverride = mInjector.getAllowNonNativeRefreshRateOverride();
459 
460         mSystemReady = false;
461     }
462 
setupSchedulerPolicies()463     public void setupSchedulerPolicies() {
464         // android.display and android.anim is critical to user experience and we should make sure
465         // it is not in the default foregroup groups, add it to top-app to make sure it uses all
466         // the cores and scheduling settings for top-app when it runs.
467         Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
468                 Process.THREAD_GROUP_TOP_APP);
469         Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
470                 Process.THREAD_GROUP_TOP_APP);
471         Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
472                 Process.THREAD_GROUP_TOP_APP);
473     }
474 
475     @Override
onStart()476     public void onStart() {
477         // We need to pre-load the persistent data store so it's ready before the default display
478         // adapter is up so that we have it's configuration. We could load it lazily, but since
479         // we're going to have to read it in eventually we may as well do it here rather than after
480         // we've waited for the display to register itself with us.
481         synchronized (mSyncRoot) {
482             mPersistentDataStore.loadIfNeeded();
483             loadStableDisplayValuesLocked();
484         }
485         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
486 
487         // If there was a runtime restart then we may have stale caches left around, so we need to
488         // make sure to invalidate them upon every start.
489         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
490 
491         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
492                 true /*allowIsolated*/);
493         publishLocalService(DisplayManagerInternal.class, new LocalService());
494     }
495 
496     @Override
onBootPhase(int phase)497     public void onBootPhase(int phase) {
498         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
499             synchronized (mSyncRoot) {
500                 long timeout = SystemClock.uptimeMillis()
501                         + mInjector.getDefaultDisplayDelayTimeout();
502                 while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null
503                         || mVirtualDisplayAdapter == null) {
504                     long delay = timeout - SystemClock.uptimeMillis();
505                     if (delay <= 0) {
506                         throw new RuntimeException("Timeout waiting for default display "
507                                 + "to be initialized. DefaultDisplay="
508                                 + mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)
509                                 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
510                     }
511                     if (DEBUG) {
512                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
513                     }
514                     try {
515                         mSyncRoot.wait(delay);
516                     } catch (InterruptedException ex) {
517                     }
518                 }
519             }
520         } else if (phase == PHASE_BOOT_COMPLETED) {
521             mDisplayModeDirector.onBootCompleted();
522         }
523     }
524 
525     @Override
onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)526     public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
527         final int newUserId = to.getUserIdentifier();
528         final int userSerial = getUserManager().getUserSerialNumber(newUserId);
529         synchronized (mSyncRoot) {
530             boolean userSwitching = mCurrentUserId != newUserId;
531             if (userSwitching) {
532                 mCurrentUserId = newUserId;
533             }
534             mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
535                 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
536                     return;
537                 }
538                 final DisplayPowerController dpc = mDisplayPowerControllers.get(
539                         logicalDisplay.getDisplayIdLocked());
540                 if (dpc == null) {
541                     return;
542                 }
543                 if (userSwitching) {
544                     BrightnessConfiguration config =
545                             getBrightnessConfigForDisplayWithPdsFallbackLocked(
546                             logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(),
547                             userSerial);
548                     dpc.setBrightnessConfiguration(config);
549                 }
550                 dpc.onSwitchUser(newUserId);
551             });
552             handleSettingsChange();
553         }
554     }
555 
556     // TODO: Use dependencies or a boot phase
windowManagerAndInputReady()557     public void windowManagerAndInputReady() {
558         synchronized (mSyncRoot) {
559             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
560             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
561 
562             DeviceStateManager deviceStateManager =
563                     mContext.getSystemService(DeviceStateManager.class);
564             deviceStateManager.registerCallback(new HandlerExecutor(mHandler),
565                     new DeviceStateListener());
566 
567             scheduleTraversalLocked(false);
568         }
569     }
570 
571     /**
572      * Called when the system is ready to go.
573      */
systemReady(boolean safeMode, boolean onlyCore)574     public void systemReady(boolean safeMode, boolean onlyCore) {
575         synchronized (mSyncRoot) {
576             mSafeMode = safeMode;
577             mOnlyCore = onlyCore;
578             mSystemReady = true;
579             // Just in case the top inset changed before the system was ready. At this point, any
580             // relevant configuration should be in place.
581             recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
582 
583             updateSettingsLocked();
584 
585             updateUserDisabledHdrTypesFromSettingsLocked();
586         }
587 
588         mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
589                 new DesiredDisplayModeSpecsObserver());
590         mDisplayModeDirector.start(mSensorManager);
591 
592         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
593 
594         mSettingsObserver = new SettingsObserver();
595 
596         mBrightnessSynchronizer.startSynchronizing();
597     }
598 
599     @VisibleForTesting
getDisplayHandler()600     Handler getDisplayHandler() {
601         return mHandler;
602     }
603 
604     @VisibleForTesting
getDisplayDeviceRepository()605     DisplayDeviceRepository getDisplayDeviceRepository() {
606         return mDisplayDeviceRepo;
607     }
608 
loadStableDisplayValuesLocked()609     private void loadStableDisplayValuesLocked() {
610         final Point size = mPersistentDataStore.getStableDisplaySize();
611         if (size.x > 0 && size.y > 0) {
612             // Just set these values directly so we don't write the display persistent data again
613             // unnecessarily
614             mStableDisplaySize.set(size.x, size.y);
615         } else {
616             final Resources res = mContext.getResources();
617             final int width = res.getInteger(
618                     com.android.internal.R.integer.config_stableDeviceDisplayWidth);
619             final int height = res.getInteger(
620                     com.android.internal.R.integer.config_stableDeviceDisplayHeight);
621             if (width > 0 && height > 0) {
622                 setStableDisplaySizeLocked(width, height);
623             }
624         }
625     }
626 
getStableDisplaySizeInternal()627     private Point getStableDisplaySizeInternal() {
628         Point r = new Point();
629         synchronized (mSyncRoot) {
630             if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
631                 r.set(mStableDisplaySize.x, mStableDisplaySize.y);
632             }
633         }
634         return r;
635     }
636 
registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)637     private void registerDisplayTransactionListenerInternal(
638             DisplayTransactionListener listener) {
639         // List is self-synchronized copy-on-write.
640         mDisplayTransactionListeners.add(listener);
641     }
642 
unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)643     private void unregisterDisplayTransactionListenerInternal(
644             DisplayTransactionListener listener) {
645         // List is self-synchronized copy-on-write.
646         mDisplayTransactionListeners.remove(listener);
647     }
648 
649     @VisibleForTesting
setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info)650     void setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info) {
651         synchronized (mSyncRoot) {
652             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
653             if (display != null) {
654                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
655                     handleLogicalDisplayChangedLocked(display);
656                     scheduleTraversalLocked(false);
657                 }
658             }
659         }
660     }
661 
662     /**
663      * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
664      */
getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)665     private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
666         synchronized (mSyncRoot) {
667             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
668             if (display != null) {
669                 display.getNonOverrideDisplayInfoLocked(outInfo);
670             }
671         }
672     }
673 
674     @VisibleForTesting
performTraversalInternal(SurfaceControl.Transaction t)675     void performTraversalInternal(SurfaceControl.Transaction t) {
676         synchronized (mSyncRoot) {
677             if (!mPendingTraversal) {
678                 return;
679             }
680             mPendingTraversal = false;
681 
682             performTraversalLocked(t);
683         }
684 
685         // List is self-synchronized copy-on-write.
686         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
687             listener.onDisplayTransaction(t);
688         }
689     }
690 
clampBrightness(int displayState, float brightnessState)691     private float clampBrightness(int displayState, float brightnessState) {
692         if (displayState == Display.STATE_OFF) {
693             brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
694         } else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT
695                 && brightnessState < PowerManager.BRIGHTNESS_MIN) {
696             brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
697         } else if (brightnessState > PowerManager.BRIGHTNESS_MAX) {
698             brightnessState = PowerManager.BRIGHTNESS_MAX;
699         }
700         return brightnessState;
701     }
702 
requestDisplayStateInternal(int displayId, int state, float brightnessState, float sdrBrightnessState)703     private void requestDisplayStateInternal(int displayId, int state, float brightnessState,
704             float sdrBrightnessState) {
705         if (state == Display.STATE_UNKNOWN) {
706             state = Display.STATE_ON;
707         }
708 
709         brightnessState = clampBrightness(state, brightnessState);
710         sdrBrightnessState = clampBrightness(state, sdrBrightnessState);
711 
712         // Update the display state within the lock.
713         // Note that we do not need to schedule traversals here although it
714         // may happen as a side-effect of displays changing state.
715         final Runnable runnable;
716         final String traceMessage;
717         synchronized (mSyncRoot) {
718             final int index = mDisplayStates.indexOfKey(displayId);
719 
720             final BrightnessPair brightnessPair =
721                     index < 0 ? null : mDisplayBrightnesses.valueAt(index);
722             if (index < 0 || (mDisplayStates.valueAt(index) == state
723                     && brightnessPair.brightness == brightnessState
724                     && brightnessPair.sdrBrightness == sdrBrightnessState)) {
725                 return; // Display no longer exists or no change.
726             }
727 
728             traceMessage = "requestDisplayStateInternal("
729                     + displayId + ", "
730                     + Display.stateToString(state)
731                     + ", brightness=" + brightnessState
732                     + ", sdrBrightness=" + sdrBrightnessState + ")";
733             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId);
734 
735             mDisplayStates.setValueAt(index, state);
736             brightnessPair.brightness = brightnessState;
737             brightnessPair.sdrBrightness = sdrBrightnessState;
738             runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId)
739                     .getPrimaryDisplayDeviceLocked());
740         }
741 
742         // Setting the display power state can take hundreds of milliseconds
743         // to complete so we defer the most expensive part of the work until
744         // after we have exited the critical section to avoid blocking other
745         // threads for a long time.
746         if (runnable != null) {
747             runnable.run();
748         }
749         Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, traceMessage, displayId);
750     }
751 
752     private class SettingsObserver extends ContentObserver {
753         SettingsObserver() {
754             super(mHandler);
755 
756             mContext.getContentResolver().registerContentObserver(
757                     Settings.Secure.getUriFor(
758                         Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED), false, this);
759         }
760 
761         @Override
762         public void onChange(boolean selfChange, Uri uri) {
763             handleSettingsChange();
764         }
765     }
766 
767     private void handleSettingsChange() {
768         synchronized (mSyncRoot) {
769             updateSettingsLocked();
770             scheduleTraversalLocked(false);
771         }
772     }
773 
774     private void updateSettingsLocked() {
775         mMinimalPostProcessingAllowed = Settings.Secure.getIntForUser(mContext.getContentResolver(),
776                 Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1, UserHandle.USER_CURRENT) != 0;
777     }
778 
779     private void updateUserDisabledHdrTypesFromSettingsLocked() {
780         mAreUserDisabledHdrTypesAllowed = (Settings.Global.getInt(
781                 mContext.getContentResolver(),
782                 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
783                 1) != 0);
784 
785         String userDisabledHdrTypes = Settings.Global.getString(mContext.getContentResolver(),
786                 Settings.Global.USER_DISABLED_HDR_FORMATS);
787 
788         if (userDisabledHdrTypes != null) {
789             try {
790                 String[] userDisabledHdrTypeStrings =
791                         TextUtils.split(userDisabledHdrTypes, ",");
792                 mUserDisabledHdrTypes = new int[userDisabledHdrTypeStrings.length];
793                 for (int i = 0; i < userDisabledHdrTypeStrings.length; i++) {
794                     mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
795                 }
796             } catch (NumberFormatException e) {
797                 Slog.e(TAG,
798                         "Failed to parse USER_DISABLED_HDR_FORMATS. "
799                                 + "Clearing the setting.", e);
800                 clearUserDisabledHdrTypesLocked();
801             }
802         } else {
803             clearUserDisabledHdrTypesLocked();
804         }
805     }
806 
807     private void clearUserDisabledHdrTypesLocked() {
808         mUserDisabledHdrTypes = new int[]{};
809         synchronized (mSyncRoot) {
810             Settings.Global.putString(mContext.getContentResolver(),
811                     Settings.Global.USER_DISABLED_HDR_FORMATS, "");
812         }
813     }
814 
815     private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
816             frameRateOverrides, DisplayInfo info, int callingUid) {
817         float frameRateHz = 0;
818         for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) {
819             if (frameRateOverride.uid == callingUid) {
820                 frameRateHz = frameRateOverride.frameRateHz;
821                 break;
822             }
823         }
824         if (frameRateHz == 0) {
825             return info;
826         }
827 
828         // Override the refresh rate only if it is a divider of the current
829         // refresh rate. This calculation needs to be in sync with the native code
830         // in RefreshRateConfigs::getFrameRateDivider
831         Display.Mode currentMode = info.getMode();
832         float numPeriods = currentMode.getRefreshRate() / frameRateHz;
833         float numPeriodsRound = Math.round(numPeriods);
834         if (Math.abs(numPeriods - numPeriodsRound) > THRESHOLD_FOR_REFRESH_RATES_DIVIDERS) {
835             return info;
836         }
837         frameRateHz = currentMode.getRefreshRate() / numPeriodsRound;
838 
839         DisplayInfo overriddenInfo = new DisplayInfo();
840         overriddenInfo.copyFrom(info);
841         for (Display.Mode mode : info.supportedModes) {
842             if (!mode.equalsExceptRefreshRate(currentMode)) {
843                 continue;
844             }
845 
846             if (mode.getRefreshRate() >= frameRateHz - THRESHOLD_FOR_REFRESH_RATES_DIVIDERS
847                     && mode.getRefreshRate()
848                     <= frameRateHz + THRESHOLD_FOR_REFRESH_RATES_DIVIDERS) {
849                 if (DEBUG) {
850                     Slog.d(TAG, "found matching modeId " + mode.getModeId());
851                 }
852                 overriddenInfo.refreshRateOverride = mode.getRefreshRate();
853 
854                 if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE,
855                         callingUid)) {
856                     overriddenInfo.modeId = mode.getModeId();
857                 }
858                 return overriddenInfo;
859             }
860         }
861 
862         if (mAllowNonNativeRefreshRateOverride) {
863             overriddenInfo.refreshRateOverride = frameRateHz;
864             if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE,
865                     callingUid)) {
866                 overriddenInfo.supportedModes = Arrays.copyOf(info.supportedModes,
867                         info.supportedModes.length + 1);
868                 overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] =
869                         new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE,
870                                 currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(),
871                                 overriddenInfo.refreshRateOverride);
872                 overriddenInfo.modeId =
873                         overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1]
874                                 .getModeId();
875             }
876             return overriddenInfo;
877         }
878 
879         return info;
880     }
881 
882     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
883         synchronized (mSyncRoot) {
884             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
885             if (display != null) {
886                 final DisplayInfo info =
887                         getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(),
888                                 display.getDisplayInfoLocked(), callingUid);
889                 if (info.hasAccess(callingUid)
890                         || isUidPresentOnDisplayInternal(callingUid, displayId)) {
891                     return info;
892                 }
893             }
894             return null;
895         }
896     }
897 
898     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid,
899             int callingUid, @EventsMask long eventsMask) {
900         synchronized (mSyncRoot) {
901             CallbackRecord record = mCallbacks.get(callingPid);
902 
903             if (record != null) {
904                 record.updateEventsMask(eventsMask);
905                 return;
906             }
907 
908             record = new CallbackRecord(callingPid, callingUid, callback, eventsMask);
909             try {
910                 IBinder binder = callback.asBinder();
911                 binder.linkToDeath(record, 0);
912             } catch (RemoteException ex) {
913                 // give up
914                 throw new RuntimeException(ex);
915             }
916 
917             mCallbacks.put(callingPid, record);
918         }
919     }
920 
921     private void onCallbackDied(CallbackRecord record) {
922         synchronized (mSyncRoot) {
923             mCallbacks.remove(record.mPid);
924             stopWifiDisplayScanLocked(record);
925         }
926     }
927 
928     private void startWifiDisplayScanInternal(int callingPid) {
929         synchronized (mSyncRoot) {
930             CallbackRecord record = mCallbacks.get(callingPid);
931             if (record == null) {
932                 throw new IllegalStateException("The calling process has not "
933                         + "registered an IDisplayManagerCallback.");
934             }
935             startWifiDisplayScanLocked(record);
936         }
937     }
938 
939     private void startWifiDisplayScanLocked(CallbackRecord record) {
940         if (!record.mWifiDisplayScanRequested) {
941             record.mWifiDisplayScanRequested = true;
942             if (mWifiDisplayScanRequestCount++ == 0) {
943                 if (mWifiDisplayAdapter != null) {
944                     mWifiDisplayAdapter.requestStartScanLocked();
945                 }
946             }
947         }
948     }
949 
950     private void stopWifiDisplayScanInternal(int callingPid) {
951         synchronized (mSyncRoot) {
952             CallbackRecord record = mCallbacks.get(callingPid);
953             if (record == null) {
954                 throw new IllegalStateException("The calling process has not "
955                         + "registered an IDisplayManagerCallback.");
956             }
957             stopWifiDisplayScanLocked(record);
958         }
959     }
960 
961     private void stopWifiDisplayScanLocked(CallbackRecord record) {
962         if (record.mWifiDisplayScanRequested) {
963             record.mWifiDisplayScanRequested = false;
964             if (--mWifiDisplayScanRequestCount == 0) {
965                 if (mWifiDisplayAdapter != null) {
966                     mWifiDisplayAdapter.requestStopScanLocked();
967                 }
968             } else if (mWifiDisplayScanRequestCount < 0) {
969                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
970                         + mWifiDisplayScanRequestCount);
971                 mWifiDisplayScanRequestCount = 0;
972             }
973         }
974     }
975 
976     private void connectWifiDisplayInternal(String address) {
977         synchronized (mSyncRoot) {
978             if (mWifiDisplayAdapter != null) {
979                 mWifiDisplayAdapter.requestConnectLocked(address);
980             }
981         }
982     }
983 
984     private void pauseWifiDisplayInternal() {
985         synchronized (mSyncRoot) {
986             if (mWifiDisplayAdapter != null) {
987                 mWifiDisplayAdapter.requestPauseLocked();
988             }
989         }
990     }
991 
992     private void resumeWifiDisplayInternal() {
993         synchronized (mSyncRoot) {
994             if (mWifiDisplayAdapter != null) {
995                 mWifiDisplayAdapter.requestResumeLocked();
996             }
997         }
998     }
999 
1000     private void disconnectWifiDisplayInternal() {
1001         synchronized (mSyncRoot) {
1002             if (mWifiDisplayAdapter != null) {
1003                 mWifiDisplayAdapter.requestDisconnectLocked();
1004             }
1005         }
1006     }
1007 
1008     private void renameWifiDisplayInternal(String address, String alias) {
1009         synchronized (mSyncRoot) {
1010             if (mWifiDisplayAdapter != null) {
1011                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
1012             }
1013         }
1014     }
1015 
1016     private void forgetWifiDisplayInternal(String address) {
1017         synchronized (mSyncRoot) {
1018             if (mWifiDisplayAdapter != null) {
1019                 mWifiDisplayAdapter.requestForgetLocked(address);
1020             }
1021         }
1022     }
1023 
1024     private WifiDisplayStatus getWifiDisplayStatusInternal() {
1025         synchronized (mSyncRoot) {
1026             if (mWifiDisplayAdapter != null) {
1027                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
1028             }
1029             return new WifiDisplayStatus();
1030         }
1031     }
1032 
1033     private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) {
1034         synchronized (mSyncRoot) {
1035             if (userDisabledHdrTypes == null) {
1036                 Slog.e(TAG, "Null is not an expected argument to "
1037                         + "setUserDisabledHdrTypesInternal");
1038                 return;
1039             }
1040             Arrays.sort(userDisabledHdrTypes);
1041             if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) {
1042                 return;
1043             }
1044             String userDisabledFormatsString = "";
1045             if (userDisabledHdrTypes.length != 0) {
1046                 userDisabledFormatsString = TextUtils.join(",",
1047                         Arrays.stream(userDisabledHdrTypes).boxed().toArray());
1048             }
1049             Settings.Global.putString(mContext.getContentResolver(),
1050                     Settings.Global.USER_DISABLED_HDR_FORMATS, userDisabledFormatsString);
1051             mUserDisabledHdrTypes = userDisabledHdrTypes;
1052             if (!mAreUserDisabledHdrTypesAllowed) {
1053                 mLogicalDisplayMapper.forEachLocked(
1054                         display -> {
1055                             display.setUserDisabledHdrTypes(userDisabledHdrTypes);
1056                             handleLogicalDisplayChangedLocked(display);
1057                         });
1058             }
1059         }
1060     }
1061 
1062     private void setAreUserDisabledHdrTypesAllowedInternal(
1063             boolean areUserDisabledHdrTypesAllowed) {
1064         synchronized (mSyncRoot) {
1065             if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) {
1066                 return;
1067             }
1068             mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed;
1069             if (mUserDisabledHdrTypes.length == 0) {
1070                 return;
1071             }
1072             Settings.Global.putInt(mContext.getContentResolver(),
1073                     Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
1074                     areUserDisabledHdrTypesAllowed ? 1 : 0);
1075             int userDisabledHdrTypes[] = {};
1076             if (!mAreUserDisabledHdrTypesAllowed) {
1077                 userDisabledHdrTypes = mUserDisabledHdrTypes;
1078             }
1079             int[] finalUserDisabledHdrTypes = userDisabledHdrTypes;
1080             mLogicalDisplayMapper.forEachLocked(
1081                     display -> {
1082                         display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes);
1083                         handleLogicalDisplayChangedLocked(display);
1084                     });
1085         }
1086     }
1087 
1088     private void requestColorModeInternal(int displayId, int colorMode) {
1089         synchronized (mSyncRoot) {
1090             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1091             if (display != null &&
1092                     display.getRequestedColorModeLocked() != colorMode) {
1093                 display.setRequestedColorModeLocked(colorMode);
1094                 scheduleTraversalLocked(false);
1095             }
1096         }
1097     }
1098 
1099     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
1100             IMediaProjection projection, int callingUid, String packageName, Surface surface,
1101             int flags, VirtualDisplayConfig virtualDisplayConfig) {
1102         synchronized (mSyncRoot) {
1103             if (mVirtualDisplayAdapter == null) {
1104                 Slog.w(TAG, "Rejecting request to create private virtual display "
1105                         + "because the virtual display adapter is not available.");
1106                 return -1;
1107             }
1108 
1109             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
1110                     callback, projection, callingUid, packageName, surface, flags,
1111                     virtualDisplayConfig);
1112             if (device == null) {
1113                 return -1;
1114             }
1115 
1116             // DisplayDevice events are handled manually for Virtual Displays.
1117             // TODO: multi-display Fix this so that generic add/remove events are not handled in a
1118             // different code path for virtual displays.  Currently this happens so that we can
1119             // return a valid display ID synchronously upon successful Virtual Display creation.
1120             // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
1121             // called on the DisplayThread (which we don't want to wait for?).
1122             // One option would be to actually wait here on the binder thread
1123             // to be notified when the virtual display is created (or failed).
1124             mDisplayDeviceRepo.onDisplayDeviceEvent(device,
1125                     DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
1126 
1127             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
1128             if (display != null) {
1129                 return display.getDisplayIdLocked();
1130             }
1131 
1132             // Something weird happened and the logical display was not created.
1133             Slog.w(TAG, "Rejecting request to create virtual display "
1134                     + "because the logical display was not created.");
1135             mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
1136             mDisplayDeviceRepo.onDisplayDeviceEvent(device,
1137                     DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1138         }
1139         return -1;
1140     }
1141 
1142     private void resizeVirtualDisplayInternal(IBinder appToken,
1143             int width, int height, int densityDpi) {
1144         synchronized (mSyncRoot) {
1145             if (mVirtualDisplayAdapter == null) {
1146                 return;
1147             }
1148 
1149             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
1150         }
1151     }
1152 
1153     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
1154         synchronized (mSyncRoot) {
1155             if (mVirtualDisplayAdapter == null) {
1156                 return;
1157             }
1158 
1159             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
1160         }
1161     }
1162 
1163     private void releaseVirtualDisplayInternal(IBinder appToken) {
1164         synchronized (mSyncRoot) {
1165             if (mVirtualDisplayAdapter == null) {
1166                 return;
1167             }
1168 
1169             DisplayDevice device =
1170                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
1171             if (device != null) {
1172                 // TODO: multi-display - handle virtual displays the same as other display adapters.
1173                 mDisplayDeviceRepo.onDisplayDeviceEvent(device,
1174                         DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1175             }
1176         }
1177     }
1178 
1179     private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) {
1180         synchronized (mSyncRoot) {
1181             if (mVirtualDisplayAdapter == null) {
1182                 return;
1183             }
1184 
1185             mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn);
1186         }
1187     }
1188 
1189     private void registerDefaultDisplayAdapters() {
1190         // Register default display adapters.
1191         synchronized (mSyncRoot) {
1192             // main display adapter
1193             registerDisplayAdapterLocked(new LocalDisplayAdapter(
1194                     mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));
1195 
1196             // Standalone VR devices rely on a virtual display as their primary display for
1197             // 2D UI. We register virtual display adapter along side the main display adapter
1198             // here so that it is ready by the time the system sends the home Intent for
1199             // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
1200             // the virtual display inside VR before any VR-specific apps even run.
1201             mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
1202                     mHandler, mDisplayDeviceRepo);
1203             if (mVirtualDisplayAdapter != null) {
1204                 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
1205             }
1206         }
1207     }
1208 
1209     private void registerAdditionalDisplayAdapters() {
1210         synchronized (mSyncRoot) {
1211             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
1212                 registerOverlayDisplayAdapterLocked();
1213                 registerWifiDisplayAdapterLocked();
1214             }
1215         }
1216     }
1217 
1218     private void registerOverlayDisplayAdapterLocked() {
1219         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
1220                 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));
1221     }
1222 
1223     private void registerWifiDisplayAdapterLocked() {
1224         if (mContext.getResources().getBoolean(
1225                 com.android.internal.R.bool.config_enableWifiDisplay)
1226                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
1227             mWifiDisplayAdapter = new WifiDisplayAdapter(
1228                     mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,
1229                     mPersistentDataStore);
1230             registerDisplayAdapterLocked(mWifiDisplayAdapter);
1231         }
1232     }
1233 
1234     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
1235         // In safe mode, we disable non-essential display adapters to give the user
1236         // an opportunity to fix broken settings or other problems that might affect
1237         // system stability.
1238         // In only-core mode, we disable non-essential display adapters to minimize
1239         // the number of dependencies that are started while in this mode and to
1240         // prevent problems that might occur due to the device being encrypted.
1241         return !mSafeMode && !mOnlyCore;
1242     }
1243 
1244     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
1245         mDisplayAdapters.add(adapter);
1246         adapter.registerLocked();
1247     }
1248 
1249     private void handleLogicalDisplayAddedLocked(LogicalDisplay display) {
1250         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
1251         final int displayId = display.getDisplayIdLocked();
1252         final boolean isDefault = displayId == Display.DEFAULT_DISPLAY;
1253         configureColorModeLocked(display, device);
1254         if (!mAreUserDisabledHdrTypesAllowed) {
1255             display.setUserDisabledHdrTypes(mUserDisabledHdrTypes);
1256         }
1257         if (isDefault) {
1258             recordStableDisplayStatsIfNeededLocked(display);
1259             recordTopInsetLocked(display);
1260         }
1261         addDisplayPowerControllerLocked(display);
1262         mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
1263 
1264         final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault;
1265         mDisplayBrightnesses.append(displayId,
1266                 new BrightnessPair(brightnessDefault, brightnessDefault));
1267 
1268         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
1269 
1270         // Wake up waitForDefaultDisplay.
1271         if (isDefault) {
1272             mSyncRoot.notifyAll();
1273         }
1274 
1275         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
1276 
1277         Runnable work = updateDisplayStateLocked(device);
1278         if (work != null) {
1279             work.run();
1280         }
1281         scheduleTraversalLocked(false);
1282     }
1283 
1284     private void handleLogicalDisplayChangedLocked(@NonNull LogicalDisplay display) {
1285         updateViewportPowerStateLocked(display);
1286 
1287         final int displayId = display.getDisplayIdLocked();
1288         if (displayId == Display.DEFAULT_DISPLAY) {
1289             recordTopInsetLocked(display);
1290         }
1291         // We don't bother invalidating the display info caches here because any changes to the
1292         // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
1293         // this point.
1294         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
1295         scheduleTraversalLocked(false);
1296         mPersistentDataStore.saveIfNeeded();
1297 
1298         DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
1299         if (dpc != null) {
1300             dpc.onDisplayChanged();
1301         }
1302     }
1303 
1304     private void handleLogicalDisplayFrameRateOverridesChangedLocked(
1305             @NonNull LogicalDisplay display) {
1306         final int displayId = display.getDisplayIdLocked();
1307         // We don't bother invalidating the display info caches here because any changes to the
1308         // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
1309         // this point.
1310         sendDisplayEventFrameRateOverrideLocked(displayId);
1311         scheduleTraversalLocked(false);
1312     }
1313 
1314     private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
1315         final int displayId = display.getDisplayIdLocked();
1316         final DisplayPowerController dpc = mDisplayPowerControllers.removeReturnOld(displayId);
1317         if (dpc != null) {
1318             dpc.stop();
1319         }
1320         mDisplayStates.delete(displayId);
1321         mDisplayBrightnesses.delete(displayId);
1322         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
1323         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
1324         scheduleTraversalLocked(false);
1325     }
1326 
1327     private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) {
1328         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
1329         final Runnable work = updateDisplayStateLocked(device);
1330         if (work != null) {
1331             mHandler.post(work);
1332         }
1333         final int displayId = display.getDisplayIdLocked();
1334         DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
1335         if (dpc != null) {
1336             dpc.onDisplayChanged();
1337         }
1338         mPersistentDataStore.saveIfNeeded();
1339         mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
1340         handleLogicalDisplayChangedLocked(display);
1341     }
1342 
1343     private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
1344         final int displayId = display.getDisplayIdLocked();
1345         final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
1346         if (dpc != null) {
1347             dpc.onDeviceStateTransition();
1348         }
1349     }
1350 
1351     private Runnable updateDisplayStateLocked(DisplayDevice device) {
1352         // Blank or unblank the display immediately to match the state requested
1353         // by the display power controller (if known).
1354         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1355         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
1356             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
1357             if (display == null) {
1358                 return null;
1359             }
1360             final int displayId = display.getDisplayIdLocked();
1361             final int state = mDisplayStates.get(displayId);
1362 
1363             // Only send a request for display state if display state has already been initialized.
1364             if (state != Display.STATE_UNKNOWN) {
1365                 final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
1366                 return device.requestDisplayStateLocked(state, brightnessPair.brightness,
1367                         brightnessPair.sdrBrightness);
1368             }
1369         }
1370         return null;
1371     }
1372 
1373     private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
1374         if (display.getPrimaryDisplayDeviceLocked() == device) {
1375             int colorMode = mPersistentDataStore.getColorMode(device);
1376             if (colorMode == Display.COLOR_MODE_INVALID) {
1377                 if ((device.getDisplayDeviceInfoLocked().flags
1378                      & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1379                     colorMode = mDefaultDisplayDefaultColorMode;
1380                 } else {
1381                     colorMode = Display.COLOR_MODE_DEFAULT;
1382                 }
1383             }
1384             display.setRequestedColorModeLocked(colorMode);
1385         }
1386     }
1387 
1388     // If we've never recorded stable device stats for this device before and they aren't
1389     // explicitly configured, go ahead and record the stable device stats now based on the status
1390     // of the default display at first boot.
1391     private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
1392         if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
1393             DisplayInfo info = d.getDisplayInfoLocked();
1394             setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
1395         }
1396     }
1397 
1398     private void recordTopInsetLocked(@Nullable LogicalDisplay d) {
1399         // We must only persist the inset after boot has completed, otherwise we will end up
1400         // overwriting the persisted value before the masking flag has been loaded from the
1401         // resource overlay.
1402         if (!mSystemReady || d == null) {
1403             return;
1404         }
1405         int topInset = d.getInsets().top;
1406         if (topInset == mDefaultDisplayTopInset) {
1407             return;
1408         }
1409         mDefaultDisplayTopInset = topInset;
1410         SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));
1411     }
1412 
1413     private void setStableDisplaySizeLocked(int width, int height) {
1414         mStableDisplaySize = new Point(width, height);
1415         try {
1416             mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
1417         } finally {
1418             mPersistentDataStore.saveIfNeeded();
1419         }
1420     }
1421 
1422     @VisibleForTesting
1423     Curve getMinimumBrightnessCurveInternal() {
1424         return mMinimumBrightnessCurve;
1425     }
1426 
1427     int getPreferredWideGamutColorSpaceIdInternal() {
1428         return mWideColorSpace.getId();
1429     }
1430 
1431     void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
1432         mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
1433     }
1434 
1435     boolean shouldAlwaysRespectAppRequestedModeInternal() {
1436         return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode();
1437     }
1438 
1439     void setRefreshRateSwitchingTypeInternal(@DisplayManager.SwitchingType int newValue) {
1440         mDisplayModeDirector.setModeSwitchingType(newValue);
1441     }
1442 
1443     @DisplayManager.SwitchingType
1444     int getRefreshRateSwitchingTypeInternal() {
1445         return mDisplayModeDirector.getModeSwitchingType();
1446     }
1447 
1448     private void setBrightnessConfigurationForDisplayInternal(
1449             @Nullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId,
1450             String packageName) {
1451         validateBrightnessConfiguration(c);
1452         final int userSerial = getUserManager().getUserSerialNumber(userId);
1453         synchronized (mSyncRoot) {
1454             try {
1455                 DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
1456                 if (displayDevice == null) {
1457                     return;
1458                 }
1459                 mPersistentDataStore.setBrightnessConfigurationForDisplayLocked(c, displayDevice,
1460                         userSerial, packageName);
1461             } finally {
1462                 mPersistentDataStore.saveIfNeeded();
1463             }
1464             if (userId != mCurrentUserId) {
1465                 return;
1466             }
1467             DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
1468             if (dpc != null) {
1469                 dpc.setBrightnessConfiguration(c);
1470             }
1471         }
1472     }
1473 
1474     private DisplayPowerController getDpcFromUniqueIdLocked(String uniqueId) {
1475         final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
1476         final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice);
1477         if (logicalDisplay != null) {
1478             final int displayId = logicalDisplay.getDisplayIdLocked();
1479             return mDisplayPowerControllers.get(displayId);
1480         }
1481         return null;
1482     }
1483 
1484     @VisibleForTesting
1485     void validateBrightnessConfiguration(BrightnessConfiguration config) {
1486         if (config == null) {
1487             return;
1488         }
1489         if (isBrightnessConfigurationTooDark(config)) {
1490             throw new IllegalArgumentException("brightness curve is too dark");
1491         }
1492     }
1493 
1494     private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
1495         Pair<float[], float[]> curve = config.getCurve();
1496         float[] lux = curve.first;
1497         float[] nits = curve.second;
1498         for (int i = 0; i < lux.length; i++) {
1499             if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
1500                 return true;
1501             }
1502         }
1503         return false;
1504     }
1505 
1506     private void loadBrightnessConfigurations() {
1507         int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
1508         synchronized (mSyncRoot) {
1509             mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> {
1510                 final String uniqueId =
1511                         logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
1512                 final BrightnessConfiguration config =
1513                         getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial);
1514                 if (config != null) {
1515                     final DisplayPowerController dpc = mDisplayPowerControllers.get(
1516                             logicalDisplay.getDisplayIdLocked());
1517                     if (dpc != null) {
1518                         dpc.setBrightnessConfiguration(config);
1519                     }
1520                 }
1521             });
1522         }
1523     }
1524 
1525     private void performTraversalLocked(SurfaceControl.Transaction t) {
1526         // Clear all viewports before configuring displays so that we can keep
1527         // track of which ones we have configured.
1528         clearViewportsLocked();
1529 
1530         // Configure each display device.
1531         mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> {
1532             final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
1533             if (device != null) {
1534                 configureDisplayLocked(t, device);
1535                 device.performTraversalLocked(t);
1536             }
1537         });
1538 
1539         // Tell the input system about these new viewports.
1540         if (mInputManagerInternal != null) {
1541             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
1542         }
1543     }
1544 
1545     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
1546             float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate,
1547             float requestedMaxRefreshRate, boolean preferMinimalPostProcessing,
1548             boolean inTraversal) {
1549         synchronized (mSyncRoot) {
1550             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1551             if (display == null) {
1552                 return;
1553             }
1554 
1555             boolean shouldScheduleTraversal = false;
1556 
1557             if (display.hasContentLocked() != hasContent) {
1558                 if (DEBUG) {
1559                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
1560                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
1561                 }
1562 
1563                 display.setHasContentLocked(hasContent);
1564                 shouldScheduleTraversal = true;
1565             }
1566             if (requestedModeId == 0 && requestedRefreshRate != 0) {
1567                 // Scan supported modes returned by display.getInfo() to find a mode with the same
1568                 // size as the default display mode but with the specified refresh rate instead.
1569                 Display.Mode mode = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
1570                         requestedRefreshRate);
1571                 if (mode != null) {
1572                     requestedModeId = mode.getModeId();
1573                 } else {
1574                     Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: "
1575                             + requestedRefreshRate + " on Display: " + displayId);
1576                 }
1577             }
1578             mDisplayModeDirector.getAppRequestObserver().setAppRequest(
1579                     displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate);
1580 
1581             if (display.getDisplayInfoLocked().minimalPostProcessingSupported) {
1582                 boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing;
1583 
1584                 if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) {
1585                     display.setRequestedMinimalPostProcessingLocked(mppRequest);
1586                     shouldScheduleTraversal = true;
1587                 }
1588             }
1589 
1590             if (shouldScheduleTraversal) {
1591                 scheduleTraversalLocked(inTraversal);
1592             }
1593         }
1594     }
1595 
1596     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
1597         synchronized (mSyncRoot) {
1598             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1599             if (display == null) {
1600                 return;
1601             }
1602             if (display.getDisplayOffsetXLocked() != x
1603                     || display.getDisplayOffsetYLocked() != y) {
1604                 if (DEBUG) {
1605                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
1606                             + x + ", " + y + ")");
1607                 }
1608                 display.setDisplayOffsetsLocked(x, y);
1609                 scheduleTraversalLocked(false);
1610             }
1611         }
1612     }
1613 
1614     private void setDisplayScalingDisabledInternal(int displayId, boolean disable) {
1615         synchronized (mSyncRoot) {
1616             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1617             if (display == null) {
1618                 return;
1619             }
1620             if (display.isDisplayScalingDisabled() != disable) {
1621                 if (DEBUG) {
1622                     Slog.d(TAG, "Display " + displayId + " content scaling disabled = " + disable);
1623                 }
1624                 display.setDisplayScalingDisabledLocked(disable);
1625                 scheduleTraversalLocked(false);
1626             }
1627         }
1628     }
1629 
1630     // Updates the lists of UIDs that are present on displays.
1631     private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
1632         synchronized (mSyncRoot) {
1633             mDisplayAccessUIDs.clear();
1634             for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) {
1635                 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i),
1636                         newDisplayAccessUIDs.valueAt(i));
1637             }
1638         }
1639     }
1640 
1641     // Checks if provided UID's content is present on the display and UID has access to it.
1642     private boolean isUidPresentOnDisplayInternal(int uid, int displayId) {
1643         synchronized (mSyncRoot) {
1644             final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId);
1645             return displayUIDs != null && displayUIDs.indexOf(uid) != -1;
1646         }
1647     }
1648 
1649     @Nullable
1650     private IBinder getDisplayToken(int displayId) {
1651         synchronized (mSyncRoot) {
1652             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1653             if (display != null) {
1654                 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
1655                 if (device != null) {
1656                     return device.getDisplayTokenLocked();
1657                 }
1658             }
1659         }
1660 
1661         return null;
1662     }
1663 
1664     private SurfaceControl.ScreenshotHardwareBuffer systemScreenshotInternal(int displayId) {
1665         synchronized (mSyncRoot) {
1666             final IBinder token = getDisplayToken(displayId);
1667             if (token == null) {
1668                 return null;
1669             }
1670             final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
1671             if (logicalDisplay == null) {
1672                 return null;
1673             }
1674 
1675             final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
1676             final SurfaceControl.DisplayCaptureArgs captureArgs =
1677                     new SurfaceControl.DisplayCaptureArgs.Builder(token)
1678                             .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
1679                             .setUseIdentityTransform(true)
1680                             .setCaptureSecureLayers(true)
1681                             .setAllowProtected(true)
1682                             .build();
1683             return SurfaceControl.captureDisplay(captureArgs);
1684         }
1685     }
1686 
1687     private SurfaceControl.ScreenshotHardwareBuffer userScreenshotInternal(int displayId) {
1688         synchronized (mSyncRoot) {
1689             final IBinder token = getDisplayToken(displayId);
1690             if (token == null) {
1691                 return null;
1692             }
1693 
1694             final SurfaceControl.DisplayCaptureArgs captureArgs =
1695                     new SurfaceControl.DisplayCaptureArgs.Builder(token)
1696                             .build();
1697             return SurfaceControl.captureDisplay(captureArgs);
1698         }
1699     }
1700 
1701     @VisibleForTesting
1702     DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal(
1703             int displayId) {
1704         final IBinder token = getDisplayToken(displayId);
1705         if (token == null) {
1706             return null;
1707         }
1708         return SurfaceControl.getDisplayedContentSamplingAttributes(token);
1709     }
1710 
1711     @VisibleForTesting
1712     boolean setDisplayedContentSamplingEnabledInternal(
1713             int displayId, boolean enable, int componentMask, int maxFrames) {
1714         final IBinder token = getDisplayToken(displayId);
1715         if (token == null) {
1716             return false;
1717         }
1718         return SurfaceControl.setDisplayedContentSamplingEnabled(
1719                 token, enable, componentMask, maxFrames);
1720     }
1721 
1722     @VisibleForTesting
1723     DisplayedContentSample getDisplayedContentSampleInternal(int displayId,
1724             long maxFrames, long timestamp) {
1725         final IBinder token = getDisplayToken(displayId);
1726         if (token == null) {
1727             return null;
1728         }
1729         return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
1730     }
1731 
1732     void resetBrightnessConfigurations() {
1733         mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
1734                 mContext.getPackageName());
1735         mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
1736             if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
1737                 return;
1738             }
1739             final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
1740             setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
1741                     mContext.getPackageName());
1742         }));
1743     }
1744 
1745     void setAutoBrightnessLoggingEnabled(boolean enabled) {
1746         synchronized (mSyncRoot) {
1747             final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
1748                     Display.DEFAULT_DISPLAY);
1749             if (displayPowerController != null) {
1750                 displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
1751             }
1752         }
1753     }
1754 
1755     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
1756         synchronized (mSyncRoot) {
1757             final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
1758                     Display.DEFAULT_DISPLAY);
1759             if (displayPowerController != null) {
1760                 displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
1761             }
1762         }
1763     }
1764 
1765     void setDisplayModeDirectorLoggingEnabled(boolean enabled) {
1766         synchronized (mSyncRoot) {
1767             if (mDisplayModeDirector != null) {
1768                 mDisplayModeDirector.setLoggingEnabled(enabled);
1769             }
1770         }
1771     }
1772 
1773     void setAmbientColorTemperatureOverride(float cct) {
1774         synchronized (mSyncRoot) {
1775             final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
1776                     Display.DEFAULT_DISPLAY);
1777             if (displayPowerController != null) {
1778                 displayPowerController.setAmbientColorTemperatureOverride(cct);
1779             }
1780         }
1781     }
1782 
1783     private void clearViewportsLocked() {
1784         mViewports.clear();
1785     }
1786 
1787     private Optional<Integer> getViewportType(DisplayDeviceInfo info) {
1788         // Get the corresponding viewport type.
1789         switch (info.touch) {
1790             case DisplayDeviceInfo.TOUCH_INTERNAL:
1791                 return Optional.of(VIEWPORT_INTERNAL);
1792             case DisplayDeviceInfo.TOUCH_EXTERNAL:
1793                 return Optional.of(VIEWPORT_EXTERNAL);
1794             case DisplayDeviceInfo.TOUCH_VIRTUAL:
1795                 if (!TextUtils.isEmpty(info.uniqueId)) {
1796                     return Optional.of(VIEWPORT_VIRTUAL);
1797                 }
1798                 // fallthrough
1799             default:
1800                 Slog.w(TAG, "Display " + info + " does not support input device matching.");
1801         }
1802         return Optional.empty();
1803     }
1804 
1805     private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
1806         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1807         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
1808 
1809         // Mirror the part of WM hierarchy that corresponds to the provided window token.
1810         IBinder windowTokenClientToMirror = device.getWindowTokenClientToMirrorLocked();
1811 
1812         // Find the logical display that the display device is showing.
1813         // Certain displays only ever show their own content.
1814         LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
1815         if (!ownContent && windowTokenClientToMirror == null) {
1816             if (display != null && !display.hasContentLocked()) {
1817                 // If the display does not have any content of its own, then
1818                 // automatically mirror the requested logical display contents if possible.
1819                 display = mLogicalDisplayMapper.getDisplayLocked(
1820                         device.getDisplayIdToMirrorLocked());
1821             }
1822             if (display == null) {
1823                 display = mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY);
1824             }
1825         }
1826 
1827         // Apply the logical display configuration to the display device.
1828         if (display == null) {
1829             // TODO: no logical display for the device, blank it
1830             Slog.w(TAG, "Missing logical display to use for physical display device: "
1831                     + device.getDisplayDeviceInfoLocked());
1832             return;
1833         }
1834         display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
1835         final Optional<Integer> viewportType = getViewportType(info);
1836         if (viewportType.isPresent()) {
1837             populateViewportLocked(viewportType.get(), display.getDisplayIdLocked(), device, info);
1838         }
1839     }
1840 
1841     /**
1842      * Get internal or external viewport. Create it if does not currently exist.
1843      * @param viewportType - either INTERNAL or EXTERNAL
1844      * @return the viewport with the requested type
1845      */
1846     private DisplayViewport getViewportLocked(int viewportType, String uniqueId) {
1847         if (viewportType != VIEWPORT_INTERNAL && viewportType != VIEWPORT_EXTERNAL
1848                 && viewportType != VIEWPORT_VIRTUAL) {
1849             Slog.wtf(TAG, "Cannot call getViewportByTypeLocked for type "
1850                     + DisplayViewport.typeToString(viewportType));
1851             return null;
1852         }
1853 
1854         DisplayViewport viewport;
1855         final int count = mViewports.size();
1856         for (int i = 0; i < count; i++) {
1857             viewport = mViewports.get(i);
1858             if (viewport.type == viewportType && uniqueId.equals(viewport.uniqueId)) {
1859                 return viewport;
1860             }
1861         }
1862 
1863         // Creates the viewport if none exists.
1864         viewport = new DisplayViewport();
1865         viewport.type = viewportType;
1866         viewport.uniqueId = uniqueId;
1867         mViewports.add(viewport);
1868         return viewport;
1869     }
1870 
1871     private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device,
1872             DisplayDeviceInfo info) {
1873         final DisplayViewport viewport = getViewportLocked(viewportType, info.uniqueId);
1874         device.populateViewportLocked(viewport);
1875         viewport.valid = true;
1876         viewport.displayId = displayId;
1877         viewport.isActive = Display.isActiveState(info.state);
1878     }
1879 
1880     private void updateViewportPowerStateLocked(LogicalDisplay display) {
1881         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
1882         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1883         final Optional<Integer> viewportType = getViewportType(info);
1884         if (viewportType.isPresent()) {
1885             for (DisplayViewport d : mViewports) {
1886                 if (d.type == viewportType.get() && info.uniqueId.equals(d.uniqueId)) {
1887                     // Update display view port power state
1888                     d.isActive = Display.isActiveState(info.state);
1889                 }
1890             }
1891             if (mInputManagerInternal != null) {
1892                 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
1893             }
1894         }
1895     }
1896 
1897     private void sendDisplayEventLocked(int displayId, @DisplayEvent int event) {
1898         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
1899         mHandler.sendMessage(msg);
1900     }
1901 
1902     private void sendDisplayGroupEvent(int groupId, int event) {
1903         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event);
1904         mHandler.sendMessage(msg);
1905     }
1906 
1907     private void sendDisplayEventFrameRateOverrideLocked(int displayId) {
1908         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
1909                 displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
1910         mHandler.sendMessage(msg);
1911     }
1912 
1913     // Requests that performTraversals be called at a
1914     // later time to apply changes to surfaces and displays.
1915     private void scheduleTraversalLocked(boolean inTraversal) {
1916         if (!mPendingTraversal && mWindowManagerInternal != null) {
1917             mPendingTraversal = true;
1918             if (!inTraversal) {
1919                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
1920             }
1921         }
1922     }
1923 
1924     // Runs on Handler thread.
1925     // Delivers display event notifications to callbacks.
1926     private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids,
1927             @DisplayEvent int event) {
1928         if (DEBUG) {
1929             Slog.d(TAG, "Delivering display event: displayId="
1930                     + displayId + ", event=" + event);
1931         }
1932 
1933         // Grab the lock and copy the callbacks.
1934         final int count;
1935         synchronized (mSyncRoot) {
1936             count = mCallbacks.size();
1937             mTempCallbacks.clear();
1938             for (int i = 0; i < count; i++) {
1939                 if (uids == null || uids.contains(mCallbacks.valueAt(i).mUid)) {
1940                     mTempCallbacks.add(mCallbacks.valueAt(i));
1941                 }
1942             }
1943         }
1944 
1945         // After releasing the lock, send the notifications out.
1946         for (int i = 0; i < mTempCallbacks.size(); i++) {
1947             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1948         }
1949         mTempCallbacks.clear();
1950     }
1951 
1952     // Runs on Handler thread.
1953     // Delivers display group event notifications to callbacks.
1954     private void deliverDisplayGroupEvent(int groupId, int event) {
1955         if (DEBUG) {
1956             Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event="
1957                     + event);
1958         }
1959 
1960         switch (event) {
1961             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED:
1962                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
1963                     listener.onDisplayGroupAdded(groupId);
1964                 }
1965                 break;
1966 
1967             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED:
1968                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
1969                     listener.onDisplayGroupChanged(groupId);
1970                 }
1971                 break;
1972 
1973             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED:
1974                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
1975                     listener.onDisplayGroupRemoved(groupId);
1976                 }
1977                 break;
1978         }
1979     }
1980 
1981     private IMediaProjectionManager getProjectionService() {
1982         if (mProjectionService == null) {
1983             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1984             mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1985         }
1986         return mProjectionService;
1987     }
1988 
1989     private UserManager getUserManager() {
1990         return mContext.getSystemService(UserManager.class);
1991     }
1992 
1993     private void dumpInternal(PrintWriter pw) {
1994         pw.println("DISPLAY MANAGER (dumpsys display)");
1995 
1996         synchronized (mSyncRoot) {
1997             pw.println("  mOnlyCode=" + mOnlyCore);
1998             pw.println("  mSafeMode=" + mSafeMode);
1999             pw.println("  mPendingTraversal=" + mPendingTraversal);
2000             pw.println("  mViewports=" + mViewports);
2001             pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
2002             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
2003             pw.println("  mStableDisplaySize=" + mStableDisplaySize);
2004             pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
2005 
2006             pw.println();
2007             if (!mAreUserDisabledHdrTypesAllowed) {
2008                 pw.println("  mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
2009                 for (int type : mUserDisabledHdrTypes) {
2010                     pw.println("  " + type);
2011                 }
2012             }
2013 
2014             pw.println();
2015             final int displayStateCount = mDisplayStates.size();
2016             pw.println("Display States: size=" + displayStateCount);
2017             for (int i = 0; i < displayStateCount; i++) {
2018                 final int displayId = mDisplayStates.keyAt(i);
2019                 final int displayState = mDisplayStates.valueAt(i);
2020                 final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i);
2021                 pw.println("  Display Id=" + displayId);
2022                 pw.println("  Display State=" + Display.stateToString(displayState));
2023                 pw.println("  Display Brightness=" + brightnessPair.brightness);
2024                 pw.println("  Display SdrBrightness=" + brightnessPair.sdrBrightness);
2025             }
2026 
2027             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
2028             ipw.increaseIndent();
2029 
2030             pw.println();
2031             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
2032             for (DisplayAdapter adapter : mDisplayAdapters) {
2033                 pw.println("  " + adapter.getName());
2034                 adapter.dumpLocked(ipw);
2035             }
2036 
2037             pw.println();
2038             pw.println("Display Devices: size=" + mDisplayDeviceRepo.sizeLocked());
2039             mDisplayDeviceRepo.forEachLocked(device -> {
2040                 pw.println("  " + device.getDisplayDeviceInfoLocked());
2041                 device.dumpLocked(ipw);
2042             });
2043 
2044             pw.println();
2045             mLogicalDisplayMapper.dumpLocked(pw);
2046 
2047             final int callbackCount = mCallbacks.size();
2048             pw.println();
2049             pw.println("Callbacks: size=" + callbackCount);
2050             for (int i = 0; i < callbackCount; i++) {
2051                 CallbackRecord callback = mCallbacks.valueAt(i);
2052                 pw.println("  " + i + ": mPid=" + callback.mPid
2053                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
2054             }
2055 
2056             final int displayPowerControllerCount = mDisplayPowerControllers.size();
2057             pw.println();
2058             pw.println("Display Power Controllers: size=" + displayPowerControllerCount);
2059             for (int i = 0; i < displayPowerControllerCount; i++) {
2060                 mDisplayPowerControllers.valueAt(i).dump(pw);
2061             }
2062             if (mBrightnessTracker != null) {
2063                 pw.println();
2064                 mBrightnessTracker.dump(pw);
2065             }
2066             pw.println();
2067             mPersistentDataStore.dump(pw);
2068         }
2069         pw.println();
2070         mDisplayModeDirector.dump(pw);
2071     }
2072 
2073     private static float[] getFloatArray(TypedArray array) {
2074         int length = array.length();
2075         float[] floatArray = new float[length];
2076         for (int i = 0; i < length; i++) {
2077             floatArray[i] = array.getFloat(i, Float.NaN);
2078         }
2079         array.recycle();
2080         return floatArray;
2081     }
2082 
2083     /**
2084      * This is the object that everything in the display manager locks on.
2085      * We make it an inner class within the {@link DisplayManagerService} to so that it is
2086      * clear that the object belongs to the display manager service and that it is
2087      * a unique object with a special purpose.
2088      */
2089     public static final class SyncRoot {
2090     }
2091 
2092     @VisibleForTesting
2093     static class Injector {
2094         VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
2095                 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
2096             return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
2097         }
2098 
2099         long getDefaultDisplayDelayTimeout() {
2100             return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
2101         }
2102 
2103         boolean getAllowNonNativeRefreshRateOverride() {
2104             return DisplayProperties
2105                     .debug_allow_non_native_refresh_rate_override().orElse(false);
2106         }
2107     }
2108 
2109     @VisibleForTesting
2110     DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
2111         synchronized (mSyncRoot) {
2112             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2113             if (display != null) {
2114                 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
2115                 return displayDevice.getDisplayDeviceInfoLocked();
2116             }
2117             return null;
2118         }
2119     }
2120 
2121     @VisibleForTesting
2122     int getDisplayIdToMirrorInternal(int displayId) {
2123         synchronized (mSyncRoot) {
2124             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2125             if (display != null) {
2126                 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
2127                 return displayDevice.getDisplayIdToMirrorLocked();
2128             }
2129             return Display.INVALID_DISPLAY;
2130         }
2131     }
2132 
2133     @VisibleForTesting
2134     Surface getVirtualDisplaySurfaceInternal(IBinder appToken) {
2135         synchronized (mSyncRoot) {
2136             if (mVirtualDisplayAdapter == null) {
2137                 return null;
2138             }
2139             return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken);
2140         }
2141     }
2142 
2143     private void initializeDisplayPowerControllersLocked() {
2144         mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
2145     }
2146 
2147     private void addDisplayPowerControllerLocked(LogicalDisplay display) {
2148         if (mPowerHandler == null) {
2149             // initPowerManagement has not yet been called.
2150             return;
2151         }
2152         if (mBrightnessTracker == null) {
2153             mBrightnessTracker = new BrightnessTracker(mContext, null);
2154         }
2155 
2156         final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
2157                 display, mSyncRoot);
2158         final DisplayPowerController displayPowerController = new DisplayPowerController(
2159                 mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
2160                 mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
2161                 () -> handleBrightnessChange(display));
2162         mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
2163     }
2164 
2165     private void handleBrightnessChange(LogicalDisplay display) {
2166         sendDisplayEventLocked(display.getDisplayIdLocked(),
2167                 DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED);
2168     }
2169 
2170     private DisplayDevice getDeviceForDisplayLocked(int displayId) {
2171         final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2172         return display == null ? null : display.getPrimaryDisplayDeviceLocked();
2173     }
2174 
2175     private BrightnessConfiguration getBrightnessConfigForDisplayWithPdsFallbackLocked(
2176             String uniqueId, int userSerial) {
2177         BrightnessConfiguration config =
2178                 mPersistentDataStore.getBrightnessConfigurationForDisplayLocked(
2179                         uniqueId, userSerial);
2180         if (config == null) {
2181             // Get from global configurations
2182             config = mPersistentDataStore.getBrightnessConfiguration(userSerial);
2183         }
2184         return config;
2185     }
2186 
2187     private final class DisplayManagerHandler extends Handler {
2188         public DisplayManagerHandler(Looper looper) {
2189             super(looper, null, true /*async*/);
2190         }
2191 
2192         @Override
2193         public void handleMessage(Message msg) {
2194             switch (msg.what) {
2195                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
2196                     registerDefaultDisplayAdapters();
2197                     break;
2198 
2199                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
2200                     registerAdditionalDisplayAdapters();
2201                     break;
2202 
2203                 case MSG_DELIVER_DISPLAY_EVENT:
2204                     deliverDisplayEvent(msg.arg1, null, msg.arg2);
2205                     break;
2206 
2207                 case MSG_REQUEST_TRAVERSAL:
2208                     mWindowManagerInternal.requestTraversalFromDisplayManager();
2209                     break;
2210 
2211                 case MSG_UPDATE_VIEWPORT: {
2212                     final boolean changed;
2213                     synchronized (mSyncRoot) {
2214                         changed = !mTempViewports.equals(mViewports);
2215                         if (changed) {
2216                             mTempViewports.clear();
2217                             for (DisplayViewport d : mViewports) {
2218                                 mTempViewports.add(d.makeCopy());
2219                             }
2220                         }
2221                     }
2222                     if (changed) {
2223                         mInputManagerInternal.setDisplayViewports(mTempViewports);
2224                     }
2225                     break;
2226                 }
2227 
2228                 case MSG_LOAD_BRIGHTNESS_CONFIGURATIONS:
2229                     loadBrightnessConfigurations();
2230                     break;
2231 
2232                 case MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
2233                     ArraySet<Integer> uids;
2234                     synchronized (mSyncRoot) {
2235                         int displayId = msg.arg1;
2236                         final LogicalDisplay display =
2237                                 mLogicalDisplayMapper.getDisplayLocked(displayId);
2238                         if (display == null) {
2239                             break;
2240                         }
2241                         uids = display.getPendingFrameRateOverrideUids();
2242                         display.clearPendingFrameRateOverrideUids();
2243                     }
2244                     deliverDisplayEvent(msg.arg1, uids, msg.arg2);
2245                     break;
2246 
2247                 case MSG_DELIVER_DISPLAY_GROUP_EVENT:
2248                     deliverDisplayGroupEvent(msg.arg1, msg.arg2);
2249                     break;
2250 
2251             }
2252         }
2253     }
2254 
2255     private final class LogicalDisplayListener implements LogicalDisplayMapper.Listener {
2256         @Override
2257         public void onLogicalDisplayEventLocked(LogicalDisplay display, int event) {
2258             switch (event) {
2259                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED:
2260                     handleLogicalDisplayAddedLocked(display);
2261                     break;
2262 
2263                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED:
2264                     handleLogicalDisplayChangedLocked(display);
2265                     break;
2266 
2267                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED:
2268                     handleLogicalDisplayRemovedLocked(display);
2269                     break;
2270 
2271                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_SWAPPED:
2272                     handleLogicalDisplaySwappedLocked(display);
2273                     break;
2274 
2275                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
2276                     handleLogicalDisplayFrameRateOverridesChangedLocked(display);
2277                     break;
2278 
2279                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION:
2280                     handleLogicalDisplayDeviceStateTransitionLocked(display);
2281                     break;
2282             }
2283         }
2284 
2285         @Override
2286         public void onDisplayGroupEventLocked(int groupId, int event) {
2287             sendDisplayGroupEvent(groupId, event);
2288         }
2289 
2290         @Override
2291         public void onTraversalRequested() {
2292             synchronized (mSyncRoot) {
2293                 scheduleTraversalLocked(false);
2294             }
2295         }
2296     }
2297 
2298     private final class CallbackRecord implements DeathRecipient {
2299         public final int mPid;
2300         public final int mUid;
2301         private final IDisplayManagerCallback mCallback;
2302         private @EventsMask AtomicLong mEventsMask;
2303 
2304         public boolean mWifiDisplayScanRequested;
2305 
2306         CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
2307                 @EventsMask long eventsMask) {
2308             mPid = pid;
2309             mUid = uid;
2310             mCallback = callback;
2311             mEventsMask = new AtomicLong(eventsMask);
2312         }
2313 
2314         public void updateEventsMask(@EventsMask long eventsMask) {
2315             mEventsMask.set(eventsMask);
2316         }
2317 
2318         @Override
2319         public void binderDied() {
2320             if (DEBUG) {
2321                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
2322             }
2323             onCallbackDied(this);
2324         }
2325 
2326         public void notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
2327             if (!shouldSendEvent(event)) {
2328                 return;
2329             }
2330 
2331             try {
2332                 mCallback.onDisplayEvent(displayId, event);
2333             } catch (RemoteException ex) {
2334                 Slog.w(TAG, "Failed to notify process "
2335                         + mPid + " that displays changed, assuming it died.", ex);
2336                 binderDied();
2337             }
2338         }
2339 
2340         private boolean shouldSendEvent(@DisplayEvent int event) {
2341             final long mask = mEventsMask.get();
2342             switch (event) {
2343                 case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
2344                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
2345                 case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
2346                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
2347                 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
2348                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0;
2349                 case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
2350                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
2351                 default:
2352                     // This should never happen.
2353                     Slog.e(TAG, "Unknown display event " + event);
2354                     return true;
2355             }
2356         }
2357     }
2358 
2359     @VisibleForTesting
2360     final class BinderService extends IDisplayManager.Stub {
2361         /**
2362          * Returns information about the specified logical display.
2363          *
2364          * @param displayId The logical display id.
2365          * @return The logical display info, return {@code null} if the display does not exist or
2366          * the calling UID isn't present on the display.  The returned object must be treated as
2367          * immutable.
2368          */
2369         @Override // Binder call
2370         public DisplayInfo getDisplayInfo(int displayId) {
2371             final int callingUid = Binder.getCallingUid();
2372             final long token = Binder.clearCallingIdentity();
2373             try {
2374                 return getDisplayInfoInternal(displayId, callingUid);
2375             } finally {
2376                 Binder.restoreCallingIdentity(token);
2377             }
2378         }
2379 
2380         /**
2381          * Returns the list of all display ids.
2382          */
2383         @Override // Binder call
2384         public int[] getDisplayIds() {
2385             final int callingUid = Binder.getCallingUid();
2386             final long token = Binder.clearCallingIdentity();
2387             try {
2388                 synchronized (mSyncRoot) {
2389                     return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid);
2390                 }
2391             } finally {
2392                 Binder.restoreCallingIdentity(token);
2393             }
2394         }
2395 
2396         @Override // Binder call
2397         public boolean isUidPresentOnDisplay(int uid, int displayId) {
2398             final long token = Binder.clearCallingIdentity();
2399             try {
2400                 return isUidPresentOnDisplayInternal(uid, displayId);
2401             } finally {
2402                 Binder.restoreCallingIdentity(token);
2403             }
2404         }
2405 
2406         /**
2407          * Returns the stable device display size, in pixels.
2408          */
2409         @Override // Binder call
2410         public Point getStableDisplaySize() {
2411             final long token = Binder.clearCallingIdentity();
2412             try {
2413                 return getStableDisplaySizeInternal();
2414             } finally {
2415                 Binder.restoreCallingIdentity(token);
2416             }
2417         }
2418 
2419         @Override // Binder call
2420         public void registerCallback(IDisplayManagerCallback callback) {
2421             registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED
2422                     | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
2423                     | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
2424         }
2425 
2426         @Override // Binder call
2427         public void registerCallbackWithEventMask(IDisplayManagerCallback callback,
2428                 @EventsMask long eventsMask) {
2429             if (callback == null) {
2430                 throw new IllegalArgumentException("listener must not be null");
2431             }
2432 
2433             final int callingPid = Binder.getCallingPid();
2434             final int callingUid = Binder.getCallingUid();
2435             final long token = Binder.clearCallingIdentity();
2436             try {
2437                 registerCallbackInternal(callback, callingPid, callingUid, eventsMask);
2438             } finally {
2439                 Binder.restoreCallingIdentity(token);
2440             }
2441         }
2442 
2443         @Override // Binder call
2444         public void startWifiDisplayScan() {
2445             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2446                     "Permission required to start wifi display scans");
2447 
2448             final int callingPid = Binder.getCallingPid();
2449             final long token = Binder.clearCallingIdentity();
2450             try {
2451                 startWifiDisplayScanInternal(callingPid);
2452             } finally {
2453                 Binder.restoreCallingIdentity(token);
2454             }
2455         }
2456 
2457         @Override // Binder call
2458         public void stopWifiDisplayScan() {
2459             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2460                     "Permission required to stop wifi display scans");
2461 
2462             final int callingPid = Binder.getCallingPid();
2463             final long token = Binder.clearCallingIdentity();
2464             try {
2465                 stopWifiDisplayScanInternal(callingPid);
2466             } finally {
2467                 Binder.restoreCallingIdentity(token);
2468             }
2469         }
2470 
2471         @Override // Binder call
2472         public void connectWifiDisplay(String address) {
2473             if (address == null) {
2474                 throw new IllegalArgumentException("address must not be null");
2475             }
2476             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2477                     "Permission required to connect to a wifi display");
2478 
2479             final long token = Binder.clearCallingIdentity();
2480             try {
2481                 connectWifiDisplayInternal(address);
2482             } finally {
2483                 Binder.restoreCallingIdentity(token);
2484             }
2485         }
2486 
2487         @Override // Binder call
2488         public void disconnectWifiDisplay() {
2489             // This request does not require special permissions.
2490             // Any app can request disconnection from the currently active wifi display.
2491             // This exception should no longer be needed once wifi display control moves
2492             // to the media router service.
2493 
2494             final long token = Binder.clearCallingIdentity();
2495             try {
2496                 disconnectWifiDisplayInternal();
2497             } finally {
2498                 Binder.restoreCallingIdentity(token);
2499             }
2500         }
2501 
2502         @Override // Binder call
2503         public void renameWifiDisplay(String address, String alias) {
2504             if (address == null) {
2505                 throw new IllegalArgumentException("address must not be null");
2506             }
2507             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2508                     "Permission required to rename to a wifi display");
2509 
2510             final long token = Binder.clearCallingIdentity();
2511             try {
2512                 renameWifiDisplayInternal(address, alias);
2513             } finally {
2514                 Binder.restoreCallingIdentity(token);
2515             }
2516         }
2517 
2518         @Override // Binder call
2519         public void forgetWifiDisplay(String address) {
2520             if (address == null) {
2521                 throw new IllegalArgumentException("address must not be null");
2522             }
2523             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2524                     "Permission required to forget to a wifi display");
2525 
2526             final long token = Binder.clearCallingIdentity();
2527             try {
2528                 forgetWifiDisplayInternal(address);
2529             } finally {
2530                 Binder.restoreCallingIdentity(token);
2531             }
2532         }
2533 
2534         @Override // Binder call
2535         public void pauseWifiDisplay() {
2536             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2537                     "Permission required to pause a wifi display session");
2538 
2539             final long token = Binder.clearCallingIdentity();
2540             try {
2541                 pauseWifiDisplayInternal();
2542             } finally {
2543                 Binder.restoreCallingIdentity(token);
2544             }
2545         }
2546 
2547         @Override // Binder call
2548         public void resumeWifiDisplay() {
2549             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
2550                     "Permission required to resume a wifi display session");
2551 
2552             final long token = Binder.clearCallingIdentity();
2553             try {
2554                 resumeWifiDisplayInternal();
2555             } finally {
2556                 Binder.restoreCallingIdentity(token);
2557             }
2558         }
2559 
2560         @Override // Binder call
2561         public WifiDisplayStatus getWifiDisplayStatus() {
2562             // This request does not require special permissions.
2563             // Any app can get information about available wifi displays.
2564 
2565             final long token = Binder.clearCallingIdentity();
2566             try {
2567                 return getWifiDisplayStatusInternal();
2568             } finally {
2569                 Binder.restoreCallingIdentity(token);
2570             }
2571         }
2572 
2573         @Override // Binder call
2574         public void setUserDisabledHdrTypes(int[] userDisabledFormats) {
2575             mContext.enforceCallingOrSelfPermission(
2576                     Manifest.permission.WRITE_SECURE_SETTINGS,
2577                     "Permission required to write the user settings.");
2578 
2579             final long token = Binder.clearCallingIdentity();
2580             try {
2581                 setUserDisabledHdrTypesInternal(userDisabledFormats);
2582             } finally {
2583                 Binder.restoreCallingIdentity(token);
2584             }
2585         }
2586 
2587         @Override // Binder call
2588         public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
2589             mContext.enforceCallingOrSelfPermission(
2590                     Manifest.permission.WRITE_SECURE_SETTINGS,
2591                     "Permission required to write the user settings.");
2592             final long token = Binder.clearCallingIdentity();
2593             try {
2594                 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed);
2595             } finally {
2596                 Binder.restoreCallingIdentity(token);
2597             }
2598         }
2599 
2600         @Override // Binder call
2601         public boolean areUserDisabledHdrTypesAllowed() {
2602             synchronized (mSyncRoot) {
2603                 return mAreUserDisabledHdrTypesAllowed;
2604             }
2605         }
2606 
2607         @Override // Binder call
2608         public int[] getUserDisabledHdrTypes() {
2609             return mUserDisabledHdrTypes;
2610         }
2611 
2612         @Override // Binder call
2613         public void requestColorMode(int displayId, int colorMode) {
2614             mContext.enforceCallingOrSelfPermission(
2615                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
2616                     "Permission required to change the display color mode");
2617             final long token = Binder.clearCallingIdentity();
2618             try {
2619                 requestColorModeInternal(displayId, colorMode);
2620             } finally {
2621                 Binder.restoreCallingIdentity(token);
2622             }
2623         }
2624 
2625         @Override // Binder call
2626         public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
2627                 IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
2628             final int callingUid = Binder.getCallingUid();
2629             if (!validatePackageName(callingUid, packageName)) {
2630                 throw new SecurityException("packageName must match the calling uid");
2631             }
2632             if (callback == null) {
2633                 throw new IllegalArgumentException("appToken must not be null");
2634             }
2635             if (virtualDisplayConfig == null) {
2636                 throw new IllegalArgumentException("virtualDisplayConfig must not be null");
2637             }
2638             final Surface surface = virtualDisplayConfig.getSurface();
2639             int flags = virtualDisplayConfig.getFlags();
2640 
2641             if (surface != null && surface.isSingleBuffered()) {
2642                 throw new IllegalArgumentException("Surface can't be single-buffered");
2643             }
2644 
2645             if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
2646                 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
2647 
2648                 // Public displays can't be allowed to show content when locked.
2649                 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
2650                     throw new IllegalArgumentException(
2651                             "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
2652                 }
2653             }
2654             if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
2655                 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
2656             }
2657             if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
2658                 flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
2659             }
2660 
2661             if (projection != null) {
2662                 try {
2663                     if (!getProjectionService().isValidMediaProjection(projection)) {
2664                         throw new SecurityException("Invalid media projection");
2665                     }
2666                     flags = projection.applyVirtualDisplayFlags(flags);
2667                 } catch (RemoteException e) {
2668                     throw new SecurityException("unable to validate media projection or flags");
2669                 }
2670             }
2671 
2672             if (callingUid != Process.SYSTEM_UID &&
2673                     (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
2674                 if (!canProjectVideo(projection)) {
2675                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
2676                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
2677                             + "MediaProjection token in order to create a screen sharing virtual "
2678                             + "display.");
2679                 }
2680             }
2681             if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
2682                 if (!canProjectSecureVideo(projection)) {
2683                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
2684                             + "or an appropriate MediaProjection token to create a "
2685                             + "secure virtual display.");
2686                 }
2687             }
2688 
2689             if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
2690                 if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
2691                     EventLog.writeEvent(0x534e4554, "162627132", callingUid,
2692                             "Attempt to create a trusted display without holding permission!");
2693                     throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
2694                             + "create a trusted virtual display.");
2695                 }
2696             }
2697 
2698             if (callingUid != Process.SYSTEM_UID
2699                     && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
2700                 if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
2701                     throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
2702                             + "create a virtual display which is not in the default DisplayGroup.");
2703                 }
2704             }
2705 
2706             if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
2707                 flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
2708             }
2709 
2710             // Sometimes users can have sensitive information in system decoration windows. An app
2711             // could create a virtual display with system decorations support and read the user info
2712             // from the surface.
2713             // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
2714             // to trusted virtual displays.
2715             final int trustedDisplayWithSysDecorFlag =
2716                     (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
2717                             | VIRTUAL_DISPLAY_FLAG_TRUSTED);
2718             if ((flags & trustedDisplayWithSysDecorFlag)
2719                     == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
2720                     && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
2721                     throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
2722             }
2723 
2724             final long token = Binder.clearCallingIdentity();
2725             try {
2726                 return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
2727                         surface, flags, virtualDisplayConfig);
2728             } finally {
2729                 Binder.restoreCallingIdentity(token);
2730             }
2731         }
2732 
2733         @Override // Binder call
2734         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
2735                 int width, int height, int densityDpi) {
2736             if (width <= 0 || height <= 0 || densityDpi <= 0) {
2737                 throw new IllegalArgumentException("width, height, and densityDpi must be "
2738                         + "greater than 0");
2739             }
2740             final long token = Binder.clearCallingIdentity();
2741             try {
2742                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
2743             } finally {
2744                 Binder.restoreCallingIdentity(token);
2745             }
2746         }
2747 
2748         @Override // Binder call
2749         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
2750             if (surface != null && surface.isSingleBuffered()) {
2751                 throw new IllegalArgumentException("Surface can't be single-buffered");
2752             }
2753             final long token = Binder.clearCallingIdentity();
2754             try {
2755                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
2756             } finally {
2757                 Binder.restoreCallingIdentity(token);
2758             }
2759         }
2760 
2761         @Override // Binder call
2762         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
2763             final long token = Binder.clearCallingIdentity();
2764             try {
2765                 releaseVirtualDisplayInternal(callback.asBinder());
2766             } finally {
2767                 Binder.restoreCallingIdentity(token);
2768             }
2769         }
2770 
2771         @Override // Binder call
2772         public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) {
2773             final long token = Binder.clearCallingIdentity();
2774             try {
2775                 setVirtualDisplayStateInternal(callback.asBinder(), isOn);
2776             } finally {
2777                 Binder.restoreCallingIdentity(token);
2778             }
2779         }
2780 
2781         @Override // Binder call
2782         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2783             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2784 
2785             final long token = Binder.clearCallingIdentity();
2786             try {
2787                 dumpInternal(pw);
2788             } finally {
2789                 Binder.restoreCallingIdentity(token);
2790             }
2791         }
2792 
2793         @Override // Binder call
2794         public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
2795             mContext.enforceCallingOrSelfPermission(
2796                     Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
2797                     "Permission to read brightness events.");
2798 
2799             final int callingUid = Binder.getCallingUid();
2800             AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
2801             final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
2802                     callingUid, callingPackage);
2803             final boolean hasUsageStats;
2804             if (mode == AppOpsManager.MODE_DEFAULT) {
2805                 // The default behavior here is to check if PackageManager has given the app
2806                 // permission.
2807                 hasUsageStats = mContext.checkCallingPermission(
2808                         Manifest.permission.PACKAGE_USAGE_STATS)
2809                         == PackageManager.PERMISSION_GRANTED;
2810             } else {
2811                 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED;
2812             }
2813 
2814             final int userId = UserHandle.getUserId(callingUid);
2815             final long token = Binder.clearCallingIdentity();
2816             try {
2817                 synchronized (mSyncRoot) {
2818                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
2819                             .getBrightnessEvents(userId, hasUsageStats);
2820                 }
2821             } finally {
2822                 Binder.restoreCallingIdentity(token);
2823             }
2824         }
2825 
2826         @Override // Binder call
2827         public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
2828             mContext.enforceCallingOrSelfPermission(
2829                     Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS,
2830                     "Permission required to to access ambient light stats.");
2831             final int callingUid = Binder.getCallingUid();
2832             final int userId = UserHandle.getUserId(callingUid);
2833             final long token = Binder.clearCallingIdentity();
2834             try {
2835                 synchronized (mSyncRoot) {
2836                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
2837                             .getAmbientBrightnessStats(userId);
2838                 }
2839             } finally {
2840                 Binder.restoreCallingIdentity(token);
2841             }
2842         }
2843 
2844         @Override // Binder call
2845         public void setBrightnessConfigurationForUser(
2846                 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
2847             mContext.enforceCallingOrSelfPermission(
2848                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2849                     "Permission required to change the display's brightness configuration");
2850             if (userId != UserHandle.getCallingUserId()) {
2851                 mContext.enforceCallingOrSelfPermission(
2852                         Manifest.permission.INTERACT_ACROSS_USERS,
2853                         "Permission required to change the display brightness"
2854                                 + " configuration of another user");
2855             }
2856             final long token = Binder.clearCallingIdentity();
2857             try {
2858                 synchronized (mSyncRoot) {
2859                     mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
2860                         if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
2861                             return;
2862                         }
2863                         final DisplayDevice displayDevice =
2864                                 logicalDisplay.getPrimaryDisplayDeviceLocked();
2865                         setBrightnessConfigurationForDisplayInternal(c, displayDevice.getUniqueId(),
2866                                 userId, packageName);
2867                     });
2868                 }
2869             } finally {
2870                 Binder.restoreCallingIdentity(token);
2871             }
2872         }
2873 
2874         @Override // Binder call
2875         public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c,
2876                 String uniqueId, int userId, String packageName) {
2877             mContext.enforceCallingOrSelfPermission(
2878                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2879                     "Permission required to change the display's brightness configuration");
2880             if (userId != UserHandle.getCallingUserId()) {
2881                 mContext.enforceCallingOrSelfPermission(
2882                         Manifest.permission.INTERACT_ACROSS_USERS,
2883                         "Permission required to change the display brightness"
2884                                 + " configuration of another user");
2885             }
2886             final long token = Binder.clearCallingIdentity();
2887             try {
2888                 setBrightnessConfigurationForDisplayInternal(c, uniqueId, userId, packageName);
2889             } finally {
2890                 Binder.restoreCallingIdentity(token);
2891             }
2892         }
2893 
2894         @Override // Binder call
2895         public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId,
2896                 int userId) {
2897             mContext.enforceCallingOrSelfPermission(
2898                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2899                     "Permission required to read the display's brightness configuration");
2900             if (userId != UserHandle.getCallingUserId()) {
2901                 mContext.enforceCallingOrSelfPermission(
2902                         Manifest.permission.INTERACT_ACROSS_USERS,
2903                         "Permission required to read the display brightness"
2904                                 + " configuration of another user");
2905             }
2906             final long token = Binder.clearCallingIdentity();
2907             final int userSerial = getUserManager().getUserSerialNumber(userId);
2908             try {
2909                 synchronized (mSyncRoot) {
2910                     // Get from per-display configurations
2911                     BrightnessConfiguration config =
2912                             getBrightnessConfigForDisplayWithPdsFallbackLocked(
2913                                     uniqueId, userSerial);
2914                     if (config == null) {
2915                         // Get default configuration
2916                         DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
2917                         if (dpc != null) {
2918                             config = dpc.getDefaultBrightnessConfiguration();
2919                         }
2920                     }
2921                     return config;
2922                 }
2923             } finally {
2924                 Binder.restoreCallingIdentity(token);
2925             }
2926         }
2927 
2928 
2929 
2930         @Override // Binder call
2931         public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
2932             final String uniqueId;
2933             synchronized (mSyncRoot) {
2934                 DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked(
2935                         Display.DEFAULT_DISPLAY).getPrimaryDisplayDeviceLocked();
2936                 uniqueId = displayDevice.getUniqueId();
2937             }
2938             return getBrightnessConfigurationForDisplay(uniqueId, userId);
2939 
2940 
2941         }
2942 
2943         @Override // Binder call
2944         public BrightnessConfiguration getDefaultBrightnessConfiguration() {
2945             mContext.enforceCallingOrSelfPermission(
2946                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2947                     "Permission required to read the display's default brightness configuration");
2948             final long token = Binder.clearCallingIdentity();
2949             try {
2950                 synchronized (mSyncRoot) {
2951                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
2952                             .getDefaultBrightnessConfiguration();
2953                 }
2954             } finally {
2955                 Binder.restoreCallingIdentity(token);
2956             }
2957         }
2958 
2959         @Override
2960         public BrightnessInfo getBrightnessInfo(int displayId) {
2961             mContext.enforceCallingOrSelfPermission(
2962                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2963                     "Permission required to read the display's brightness info.");
2964             final long token = Binder.clearCallingIdentity();
2965             try {
2966                 synchronized (mSyncRoot) {
2967                     DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
2968                     if (dpc != null) {
2969                         return dpc.getBrightnessInfo();
2970                     }
2971                 }
2972             } finally {
2973                 Binder.restoreCallingIdentity(token);
2974             }
2975             return null;
2976         }
2977 
2978         @Override // Binder call
2979         public boolean isMinimalPostProcessingRequested(int displayId) {
2980             synchronized (mSyncRoot) {
2981                 return mLogicalDisplayMapper.getDisplayLocked(displayId)
2982                         .getRequestedMinimalPostProcessingLocked();
2983             }
2984         }
2985 
2986         @Override // Binder call
2987         public void setTemporaryBrightness(int displayId, float brightness) {
2988             mContext.enforceCallingOrSelfPermission(
2989                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2990                     "Permission required to set the display's brightness");
2991             final long token = Binder.clearCallingIdentity();
2992             try {
2993                 synchronized (mSyncRoot) {
2994                     mDisplayPowerControllers.get(displayId)
2995                             .setTemporaryBrightness(brightness);
2996                 }
2997             } finally {
2998                 Binder.restoreCallingIdentity(token);
2999             }
3000         }
3001 
3002         @Override // Binder call
3003         public void setBrightness(int displayId, float brightness) {
3004             mContext.enforceCallingOrSelfPermission(
3005                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
3006                     "Permission required to set the display's brightness");
3007             if (!isValidBrightness(brightness)) {
3008                 Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
3009                 return;
3010             }
3011             final long token = Binder.clearCallingIdentity();
3012             try {
3013                 synchronized (mSyncRoot) {
3014                     DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
3015                     if (dpc != null) {
3016                         dpc.putScreenBrightnessSetting(brightness);
3017                     }
3018                     mPersistentDataStore.saveIfNeeded();
3019                 }
3020             } finally {
3021                 Binder.restoreCallingIdentity(token);
3022             }
3023         }
3024 
3025         @Override // Binder call
3026         public float getBrightness(int displayId) {
3027             float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
3028             mContext.enforceCallingOrSelfPermission(
3029                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
3030                     "Permission required to set the display's brightness");
3031             final long token = Binder.clearCallingIdentity();
3032             try {
3033                 synchronized (mSyncRoot) {
3034                     DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
3035                     if (dpc != null) {
3036                         brightness = dpc.getScreenBrightnessSetting();
3037                     }
3038                 }
3039             } finally {
3040                 Binder.restoreCallingIdentity(token);
3041             }
3042             return brightness;
3043         }
3044 
3045         @Override // Binder call
3046         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
3047             mContext.enforceCallingOrSelfPermission(
3048                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
3049                     "Permission required to set the display's auto brightness adjustment");
3050             final long token = Binder.clearCallingIdentity();
3051             try {
3052                 synchronized (mSyncRoot) {
3053                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
3054                             .setTemporaryAutoBrightnessAdjustment(adjustment);
3055                 }
3056             } finally {
3057                 Binder.restoreCallingIdentity(token);
3058             }
3059         }
3060 
3061         @Override // Binder call
3062         public void onShellCommand(FileDescriptor in, FileDescriptor out,
3063                 FileDescriptor err, String[] args, ShellCallback callback,
3064                 ResultReceiver resultReceiver) {
3065             new DisplayManagerShellCommand(DisplayManagerService.this).exec(this, in, out, err,
3066                     args, callback, resultReceiver);
3067         }
3068 
3069         @Override // Binder call
3070         public Curve getMinimumBrightnessCurve() {
3071             final long token = Binder.clearCallingIdentity();
3072             try {
3073                 return getMinimumBrightnessCurveInternal();
3074             } finally {
3075                 Binder.restoreCallingIdentity(token);
3076             }
3077         }
3078 
3079         @Override // Binder call
3080         public int getPreferredWideGamutColorSpaceId() {
3081             final long token = Binder.clearCallingIdentity();
3082             try {
3083                 return getPreferredWideGamutColorSpaceIdInternal();
3084             } finally {
3085                 Binder.restoreCallingIdentity(token);
3086             }
3087         }
3088 
3089         @Override // Binder call
3090         public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
3091             mContext.enforceCallingOrSelfPermission(
3092                     Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
3093                     "Permission required to override display mode requests.");
3094             final long token = Binder.clearCallingIdentity();
3095             try {
3096                 setShouldAlwaysRespectAppRequestedModeInternal(enabled);
3097             } finally {
3098                 Binder.restoreCallingIdentity(token);
3099             }
3100         }
3101 
3102         @Override // Binder call
3103         public boolean shouldAlwaysRespectAppRequestedMode() {
3104             mContext.enforceCallingOrSelfPermission(
3105                     Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
3106                     "Permission required to override display mode requests.");
3107             final long token = Binder.clearCallingIdentity();
3108             try {
3109                 return shouldAlwaysRespectAppRequestedModeInternal();
3110             } finally {
3111                 Binder.restoreCallingIdentity(token);
3112             }
3113         }
3114 
3115         @Override // Binder call
3116         public void setRefreshRateSwitchingType(int newValue) {
3117             mContext.enforceCallingOrSelfPermission(
3118                     Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
3119                     "Permission required to modify refresh rate switching type.");
3120             final long token = Binder.clearCallingIdentity();
3121             try {
3122                 setRefreshRateSwitchingTypeInternal(newValue);
3123             } finally {
3124                 Binder.restoreCallingIdentity(token);
3125             }
3126         }
3127 
3128         @Override // Binder call
3129         public int getRefreshRateSwitchingType() {
3130             final long token = Binder.clearCallingIdentity();
3131             try {
3132                 return getRefreshRateSwitchingTypeInternal();
3133             } finally {
3134                 Binder.restoreCallingIdentity(token);
3135             }
3136         }
3137 
3138         private boolean validatePackageName(int uid, String packageName) {
3139             if (packageName != null) {
3140                 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
3141                 if (packageNames != null) {
3142                     for (String n : packageNames) {
3143                         if (n.equals(packageName)) {
3144                             return true;
3145                         }
3146                     }
3147                 }
3148             }
3149             return false;
3150         }
3151 
3152         private boolean canProjectVideo(IMediaProjection projection) {
3153             if (projection != null) {
3154                 try {
3155                     if (projection.canProjectVideo()) {
3156                         return true;
3157                     }
3158                 } catch (RemoteException e) {
3159                     Slog.e(TAG, "Unable to query projection service for permissions", e);
3160                 }
3161             }
3162             if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
3163                 return true;
3164             }
3165             return canProjectSecureVideo(projection);
3166         }
3167 
3168         private boolean canProjectSecureVideo(IMediaProjection projection) {
3169             if (projection != null) {
3170                 try {
3171                     if (projection.canProjectSecureVideo()){
3172                         return true;
3173                     }
3174                 } catch (RemoteException e) {
3175                     Slog.e(TAG, "Unable to query projection service for permissions", e);
3176                 }
3177             }
3178             return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
3179         }
3180 
3181         private boolean checkCallingPermission(String permission, String func) {
3182             if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
3183                 return true;
3184             }
3185             final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
3186                     + ", uid=" + Binder.getCallingUid() + " requires " + permission;
3187             Slog.w(TAG, msg);
3188             return false;
3189         }
3190 
3191     }
3192 
3193     private static boolean isValidBrightness(float brightness) {
3194         return !Float.isNaN(brightness)
3195                 && (brightness >= PowerManager.BRIGHTNESS_MIN)
3196                 && (brightness <= PowerManager.BRIGHTNESS_MAX);
3197     }
3198 
3199     private final class LocalService extends DisplayManagerInternal {
3200 
3201         @Override
3202         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
3203                 SensorManager sensorManager) {
3204             synchronized (mSyncRoot) {
3205                 mDisplayPowerCallbacks = callbacks;
3206                 mSensorManager = sensorManager;
3207                 mPowerHandler = handler;
3208                 initializeDisplayPowerControllersLocked();
3209             }
3210 
3211             mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
3212         }
3213 
3214         @Override
3215         public boolean requestPowerState(int groupId, DisplayPowerRequest request,
3216                 boolean waitForNegativeProximity) {
3217             synchronized (mSyncRoot) {
3218                 final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
3219                         groupId);
3220                 if (displayGroup == null) {
3221                     return true;
3222                 }
3223 
3224                 final int size = displayGroup.getSizeLocked();
3225                 boolean ready = true;
3226                 for (int i = 0; i < size; i++) {
3227                     final int id = displayGroup.getIdLocked(i);
3228                     final DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked(
3229                             id).getPrimaryDisplayDeviceLocked();
3230                     final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
3231                     if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
3232                         final DisplayPowerController displayPowerController =
3233                                 mDisplayPowerControllers.get(id);
3234                         ready &= displayPowerController.requestPowerState(request,
3235                                 waitForNegativeProximity);
3236                     }
3237                 }
3238 
3239                 return ready;
3240             }
3241         }
3242 
3243         @Override
3244         public boolean isProximitySensorAvailable() {
3245             synchronized (mSyncRoot) {
3246                 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
3247                         .isProximitySensorAvailable();
3248             }
3249         }
3250 
3251         @Override
3252         public void registerDisplayGroupListener(DisplayGroupListener listener) {
3253             mDisplayGroupListeners.add(listener);
3254         }
3255 
3256         @Override
3257         public void unregisterDisplayGroupListener(DisplayGroupListener listener) {
3258             mDisplayGroupListeners.remove(listener);
3259         }
3260 
3261         @Override
3262         public SurfaceControl.ScreenshotHardwareBuffer systemScreenshot(int displayId) {
3263             return systemScreenshotInternal(displayId);
3264         }
3265 
3266         @Override
3267         public SurfaceControl.ScreenshotHardwareBuffer userScreenshot(int displayId) {
3268             return userScreenshotInternal(displayId);
3269         }
3270 
3271         @Override
3272         public DisplayInfo getDisplayInfo(int displayId) {
3273             return getDisplayInfoInternal(displayId, Process.myUid());
3274         }
3275 
3276         @Override
3277         public Point getDisplayPosition(int displayId) {
3278             synchronized (mSyncRoot) {
3279                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
3280                 if (display != null) {
3281                     return display.getDisplayPosition();
3282                 }
3283                 return null;
3284             }
3285         }
3286 
3287         @Override
3288         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
3289             if (listener == null) {
3290                 throw new IllegalArgumentException("listener must not be null");
3291             }
3292 
3293             registerDisplayTransactionListenerInternal(listener);
3294         }
3295 
3296         @Override
3297         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
3298             if (listener == null) {
3299                 throw new IllegalArgumentException("listener must not be null");
3300             }
3301 
3302             unregisterDisplayTransactionListenerInternal(listener);
3303         }
3304 
3305         @Override
3306         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
3307             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
3308         }
3309 
3310         @Override
3311         public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
3312             getNonOverrideDisplayInfoInternal(displayId, outInfo);
3313         }
3314 
3315         @Override
3316         public void performTraversal(SurfaceControl.Transaction t) {
3317             performTraversalInternal(t);
3318         }
3319 
3320         @Override
3321         public void setDisplayProperties(int displayId, boolean hasContent,
3322                 float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate,
3323                 float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,
3324                 boolean inTraversal) {
3325             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
3326                     requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate,
3327                     requestedMinimalPostProcessing, inTraversal);
3328         }
3329 
3330         @Override
3331         public void setDisplayOffsets(int displayId, int x, int y) {
3332             setDisplayOffsetsInternal(displayId, x, y);
3333         }
3334 
3335         @Override
3336         public void setDisplayScalingDisabled(int displayId, boolean disableScaling) {
3337             setDisplayScalingDisabledInternal(displayId, disableScaling);
3338         }
3339 
3340         @Override
3341         public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
3342             setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
3343         }
3344 
3345         @Override
3346         public void persistBrightnessTrackerState() {
3347             synchronized (mSyncRoot) {
3348                 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
3349                         .persistBrightnessTrackerState();
3350             }
3351         }
3352 
3353         @Override
3354         public void onOverlayChanged() {
3355             synchronized (mSyncRoot) {
3356                 mDisplayDeviceRepo.forEachLocked(DisplayDevice::onOverlayChangedLocked);
3357             }
3358         }
3359 
3360         @Override
3361         public DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributes(
3362                 int displayId) {
3363             return getDisplayedContentSamplingAttributesInternal(displayId);
3364         }
3365 
3366         @Override
3367         public boolean setDisplayedContentSamplingEnabled(
3368                 int displayId, boolean enable, int componentMask, int maxFrames) {
3369             return setDisplayedContentSamplingEnabledInternal(
3370                     displayId, enable, componentMask, maxFrames);
3371         }
3372 
3373         @Override
3374         public DisplayedContentSample getDisplayedContentSample(int displayId,
3375                 long maxFrames, long timestamp) {
3376             return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp);
3377         }
3378 
3379         @Override
3380         public void ignoreProximitySensorUntilChanged() {
3381             mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
3382                     .ignoreProximitySensorUntilChanged();
3383         }
3384 
3385         @Override
3386         public int getRefreshRateSwitchingType() {
3387             return getRefreshRateSwitchingTypeInternal();
3388         }
3389 
3390         @Override
3391         public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName,
3392                 String sensorType) {
3393             final SensorManager sensorManager;
3394             synchronized (mSyncRoot) {
3395                 sensorManager = mSensorManager;
3396             }
3397             if (sensorManager == null) {
3398                 return null;
3399             }
3400 
3401             // Verify that the specified sensor exists.
3402             final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName,
3403                     SensorUtils.NO_FALLBACK);
3404             if (sensor == null) {
3405                 return null;
3406             }
3407 
3408             synchronized (mSyncRoot) {
3409                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
3410                 if (display == null) {
3411                     return null;
3412                 }
3413                 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
3414                 if (device == null) {
3415                     return null;
3416                 }
3417                 final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
3418                 SensorData sensorData = config.getProximitySensor();
3419                 if (sensorData.matches(sensorName, sensorType)) {
3420                     return new RefreshRateRange(sensorData.minRefreshRate,
3421                             sensorData.maxRefreshRate);
3422                 }
3423             }
3424             return null;
3425         }
3426 
3427         @Override
3428         public List<RefreshRateLimitation> getRefreshRateLimitations(int displayId) {
3429             final DisplayDeviceConfig config;
3430             synchronized (mSyncRoot) {
3431                 final DisplayDevice device = getDeviceForDisplayLocked(displayId);
3432                 if (device == null) {
3433                     return null;
3434                 }
3435                 config = device.getDisplayDeviceConfig();
3436             }
3437             return config.getRefreshRateLimitations();
3438         }
3439 
3440         @Override
3441         public IBinder getWindowTokenClientToMirror(int displayId) {
3442             final DisplayDevice device;
3443             synchronized (mSyncRoot) {
3444                 device = getDeviceForDisplayLocked(displayId);
3445                 if (device == null) {
3446                     return null;
3447                 }
3448             }
3449             return device.getWindowTokenClientToMirrorLocked();
3450         }
3451 
3452         @Override
3453         public void setWindowTokenClientToMirror(int displayId, IBinder windowToken) {
3454             synchronized (mSyncRoot) {
3455                 final DisplayDevice device = getDeviceForDisplayLocked(displayId);
3456                 if (device != null) {
3457                     device.setWindowTokenClientToMirrorLocked(windowToken);
3458                 }
3459             }
3460         }
3461 
3462         @Override
3463         public Point getDisplaySurfaceDefaultSize(int displayId) {
3464             final DisplayDevice device;
3465             synchronized (mSyncRoot) {
3466                 device = getDeviceForDisplayLocked(displayId);
3467                 if (device == null) {
3468                     return null;
3469                 }
3470             }
3471             return device.getDisplaySurfaceDefaultSize();
3472         }
3473     }
3474 
3475     class DesiredDisplayModeSpecsObserver
3476             implements DisplayModeDirector.DesiredDisplayModeSpecsListener {
3477 
3478         private final Consumer<LogicalDisplay> mSpecsChangedConsumer = display -> {
3479             int displayId = display.getDisplayIdLocked();
3480             DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
3481                     mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId);
3482             DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs =
3483                     display.getDesiredDisplayModeSpecsLocked();
3484             if (DEBUG) {
3485                 Slog.i(TAG,
3486                         "Comparing display specs: " + desiredDisplayModeSpecs
3487                                 + ", existing: " + existingDesiredDisplayModeSpecs);
3488             }
3489             if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) {
3490                 display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs);
3491                 mChanged = true;
3492             }
3493         };
3494 
3495         @GuardedBy("mSyncRoot")
3496         private boolean mChanged = false;
3497 
3498         public void onDesiredDisplayModeSpecsChanged() {
3499             synchronized (mSyncRoot) {
3500                 mChanged = false;
3501                 mLogicalDisplayMapper.forEachLocked(mSpecsChangedConsumer);
3502                 if (mChanged) {
3503                     scheduleTraversalLocked(false);
3504                     mChanged = false;
3505                 }
3506             }
3507         }
3508     }
3509 
3510     /**
3511      * Listens to changes in device state and reports the state to LogicalDisplayMapper.
3512      */
3513     class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
3514         @Override
3515         public void onStateChanged(int deviceState) {
3516             synchronized (mSyncRoot) {
3517                 mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
3518             }
3519         }
3520     };
3521 
3522     private class BrightnessPair {
3523         public float brightness;
3524         public float sdrBrightness;
3525 
3526         BrightnessPair(float brightness, float sdrBrightness) {
3527             this.brightness = brightness;
3528             this.sdrBrightness = sdrBrightness;
3529         }
3530     }
3531 
3532     /**
3533      * Functional interface for providing time.
3534      * TODO(b/184781936): merge with PowerManagerService.Clock
3535      */
3536     @VisibleForTesting
3537     public interface Clock {
3538         /**
3539          * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
3540          */
3541         long uptimeMillis();
3542     }
3543 }
3544