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