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