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.Manifest.permission.MANAGE_DISPLAYS;
25 import static android.Manifest.permission.RESTRICT_DISPLAY_MODES;
26 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
27 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
28 import static android.hardware.display.DisplayManager.EventsMask;
29 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
30 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
31 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
32 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP;
33 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
34 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
35 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
36 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
37 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
38 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
39 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
40 import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
41 import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
42 import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
43 import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
44 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED;
45 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
46 import static android.os.Process.FIRST_APPLICATION_UID;
47 import static android.os.Process.ROOT_UID;
48 import static android.provider.Settings.Secure.RESOLUTION_MODE_FULL;
49 import static android.provider.Settings.Secure.RESOLUTION_MODE_HIGH;
50 import static android.provider.Settings.Secure.RESOLUTION_MODE_UNKNOWN;
51 
52 import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
53 
54 import android.Manifest;
55 import android.annotation.EnforcePermission;
56 import android.annotation.NonNull;
57 import android.annotation.Nullable;
58 import android.annotation.RequiresPermission;
59 import android.annotation.SuppressLint;
60 import android.annotation.UserIdInt;
61 import android.app.ActivityManager;
62 import android.app.ActivityManagerInternal;
63 import android.app.AppOpsManager;
64 import android.app.compat.CompatChanges;
65 import android.companion.virtual.IVirtualDevice;
66 import android.companion.virtual.VirtualDeviceManager;
67 import android.companion.virtual.flags.Flags;
68 import android.compat.annotation.ChangeId;
69 import android.compat.annotation.EnabledSince;
70 import android.content.BroadcastReceiver;
71 import android.content.Context;
72 import android.content.Intent;
73 import android.content.IntentFilter;
74 import android.content.pm.PackageManager;
75 import android.content.pm.ParceledListSlice;
76 import android.content.res.Resources;
77 import android.content.res.TypedArray;
78 import android.database.ContentObserver;
79 import android.graphics.ColorSpace;
80 import android.graphics.Point;
81 import android.hardware.OverlayProperties;
82 import android.hardware.Sensor;
83 import android.hardware.SensorManager;
84 import android.hardware.devicestate.DeviceState;
85 import android.hardware.devicestate.DeviceStateManager;
86 import android.hardware.devicestate.DeviceStateManagerInternal;
87 import android.hardware.display.AmbientBrightnessDayStats;
88 import android.hardware.display.BrightnessChangeEvent;
89 import android.hardware.display.BrightnessConfiguration;
90 import android.hardware.display.BrightnessInfo;
91 import android.hardware.display.Curve;
92 import android.hardware.display.DisplayManager;
93 import android.hardware.display.DisplayManagerGlobal;
94 import android.hardware.display.DisplayManagerInternal;
95 import android.hardware.display.DisplayManagerInternal.DisplayGroupListener;
96 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
97 import android.hardware.display.DisplayViewport;
98 import android.hardware.display.DisplayedContentSample;
99 import android.hardware.display.DisplayedContentSamplingAttributes;
100 import android.hardware.display.HdrConversionMode;
101 import android.hardware.display.IDisplayManager;
102 import android.hardware.display.IDisplayManagerCallback;
103 import android.hardware.display.IVirtualDisplayCallback;
104 import android.hardware.display.VirtualDisplayConfig;
105 import android.hardware.display.WifiDisplayStatus;
106 import android.hardware.graphics.common.DisplayDecorationSupport;
107 import android.hardware.input.HostUsiVersion;
108 import android.media.projection.IMediaProjection;
109 import android.media.projection.IMediaProjectionManager;
110 import android.net.Uri;
111 import android.os.Binder;
112 import android.os.Handler;
113 import android.os.HandlerExecutor;
114 import android.os.IBinder;
115 import android.os.IBinder.DeathRecipient;
116 import android.os.IThermalService;
117 import android.os.Looper;
118 import android.os.Message;
119 import android.os.PowerManager;
120 import android.os.Process;
121 import android.os.RemoteException;
122 import android.os.ResultReceiver;
123 import android.os.ServiceManager;
124 import android.os.ShellCallback;
125 import android.os.SystemClock;
126 import android.os.SystemProperties;
127 import android.os.Trace;
128 import android.os.UserHandle;
129 import android.os.UserManager;
130 import android.provider.DeviceConfigInterface;
131 import android.provider.Settings;
132 import android.sysprop.DisplayProperties;
133 import android.text.TextUtils;
134 import android.util.ArraySet;
135 import android.util.EventLog;
136 import android.util.IndentingPrintWriter;
137 import android.util.IntArray;
138 import android.util.Pair;
139 import android.util.Slog;
140 import android.util.SparseArray;
141 import android.util.SparseIntArray;
142 import android.util.Spline;
143 import android.view.ContentRecordingSession;
144 import android.view.Display;
145 import android.view.DisplayEventReceiver;
146 import android.view.DisplayInfo;
147 import android.view.Surface;
148 import android.view.SurfaceControl;
149 import android.view.SurfaceControl.RefreshRateRange;
150 import android.window.DisplayWindowPolicyController;
151 import android.window.ScreenCapture;
152 
153 import com.android.internal.annotations.GuardedBy;
154 import com.android.internal.annotations.VisibleForTesting;
155 import com.android.internal.display.BrightnessSynchronizer;
156 import com.android.internal.foldables.FoldGracePeriodProvider;
157 import com.android.internal.foldables.FoldLockSettingAvailabilityProvider;
158 import com.android.internal.os.BackgroundThread;
159 import com.android.internal.util.ArrayUtils;
160 import com.android.internal.util.DumpUtils;
161 import com.android.internal.util.FrameworkStatsLog;
162 import com.android.internal.util.SettingsWrapper;
163 import com.android.server.AnimationThread;
164 import com.android.server.DisplayThread;
165 import com.android.server.LocalServices;
166 import com.android.server.SystemService;
167 import com.android.server.UiThread;
168 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
169 import com.android.server.display.config.SensorData;
170 import com.android.server.display.feature.DeviceConfigParameterProvider;
171 import com.android.server.display.feature.DisplayManagerFlags;
172 import com.android.server.display.layout.Layout;
173 import com.android.server.display.mode.DisplayModeDirector;
174 import com.android.server.display.notifications.DisplayNotificationManager;
175 import com.android.server.display.utils.DebugUtils;
176 import com.android.server.display.utils.SensorUtils;
177 import com.android.server.input.InputManagerInternal;
178 import com.android.server.utils.FoldSettingProvider;
179 import com.android.server.wm.SurfaceAnimationThread;
180 import com.android.server.wm.WindowManagerInternal;
181 
182 import java.io.FileDescriptor;
183 import java.io.PrintWriter;
184 import java.util.ArrayList;
185 import java.util.Arrays;
186 import java.util.List;
187 import java.util.Optional;
188 import java.util.Set;
189 import java.util.concurrent.CopyOnWriteArrayList;
190 import java.util.concurrent.atomic.AtomicLong;
191 import java.util.function.Consumer;
192 
193 
194 /**
195  * Manages attached displays.
196  * <p>
197  * The {@link DisplayManagerService} manages the global lifecycle of displays,
198  * decides how to configure logical displays based on the physical display devices currently
199  * attached, sends notifications to the system and to applications when the state
200  * changes, and so on.
201  * </p><p>
202  * The display manager service relies on a collection of {@link DisplayAdapter} components,
203  * for discovering and configuring physical display devices attached to the system.
204  * There are separate display adapters for each manner that devices are attached:
205  * one display adapter for physical displays, one for simulated non-functional
206  * displays when the system is headless, one for simulated overlay displays used for
207  * development, one for wifi displays, etc.
208  * </p><p>
209  * Display adapters are only weakly coupled to the display manager service.
210  * Display adapters communicate changes in display device state to the display manager
211  * service asynchronously via a {@link DisplayAdapter.Listener}, and through
212  * the {@link DisplayDeviceRepository.Listener}, which is ultimately registered
213  * by the display manager service.  This separation of concerns is important for
214  * two main reasons.  First, it neatly encapsulates the responsibilities of these
215  * two classes: display adapters handle individual display devices whereas
216  * the display manager service handles the global state.  Second, it eliminates
217  * the potential for deadlocks resulting from asynchronous display device discovery.
218  * </p>
219  *
220  * <h3>Synchronization</h3>
221  * <p>
222  * Because the display manager may be accessed by multiple threads, the synchronization
223  * story gets a little complicated.  In particular, the window manager may call into
224  * the display manager while holding a surface transaction with the expectation that
225  * it can apply changes immediately.  Unfortunately, that means we can't just do
226  * everything asynchronously (*grump*).
227  * </p><p>
228  * To make this work, all of the objects that belong to the display manager must
229  * use the same lock.  We call this lock the synchronization root and it has a unique
230  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
231  * named with the "Locked" suffix.
232  * </p><p>
233  * Where things get tricky is that the display manager is not allowed to make
234  * any potentially reentrant calls, especially into the window manager.  We generally
235  * avoid this by making all potentially reentrant out-calls asynchronous.
236  * </p>
237  */
238 @SuppressWarnings("MissingPermission")
239 public final class DisplayManagerService extends SystemService {
240     private static final String TAG = "DisplayManagerService";
241 
242     // To enable these logs, run:
243     // 'adb shell setprop persist.log.tag.DisplayManagerService DEBUG && adb reboot'
244     private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
245 
246     // When this system property is set to 0, WFD is forcibly disabled on boot.
247     // When this system property is set to 1, WFD is forcibly enabled on boot.
248     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
249     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
250 
251     private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
252 
253     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
254     // This value needs to be in sync with the threshold
255     // in RefreshRateConfigs::getFrameRateDivisor.
256     private static final float THRESHOLD_FOR_REFRESH_RATES_DIVISORS = 0.0009f;
257 
258     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
259     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
260     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
261     private static final int MSG_REQUEST_TRAVERSAL = 4;
262     private static final int MSG_UPDATE_VIEWPORT = 5;
263     private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6;
264     private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
265     private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
266     private static final int MSG_RECEIVED_DEVICE_STATE = 9;
267     private static final int[] EMPTY_ARRAY = new int[0];
268     private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode(
269             HDR_CONVERSION_UNSUPPORTED);
270 
271     private final Context mContext;
272     private final DisplayManagerHandler mHandler;
273     private final Handler mUiHandler;
274     private final DisplayModeDirector mDisplayModeDirector;
275     private final ExternalDisplayPolicy mExternalDisplayPolicy;
276     private WindowManagerInternal mWindowManagerInternal;
277     private InputManagerInternal mInputManagerInternal;
278     private ActivityManagerInternal mActivityManagerInternal;
279     private final UidImportanceListener mUidImportanceListener = new UidImportanceListener();
280     @Nullable
281     private IMediaProjectionManager mProjectionService;
282     private DeviceStateManagerInternal mDeviceStateManager;
283     @GuardedBy("mSyncRoot")
284     private int[] mUserDisabledHdrTypes = {};
285     @Display.HdrCapabilities.HdrType
286     private int[] mSupportedHdrOutputType;
287     @GuardedBy("mSyncRoot")
288     private boolean mAreUserDisabledHdrTypesAllowed = true;
289 
290     // This value indicates whether or not HDR output control is enabled.
291     // It is read from DeviceConfig and is updated via a listener if the config changes.
292     private volatile boolean mIsHdrOutputControlEnabled;
293 
294     // Display mode chosen by user.
295     private Display.Mode mUserPreferredMode;
296     @HdrConversionMode.ConversionMode
297     private final int mDefaultHdrConversionMode;
298     // HDR conversion mode chosen by user
299     @GuardedBy("mSyncRoot")
300     private HdrConversionMode mHdrConversionMode = null;
301     // Actual HDR conversion mode, which takes app overrides into account.
302     private HdrConversionMode mOverrideHdrConversionMode = null;
303     @GuardedBy("mSyncRoot")
304     private int mSystemPreferredHdrOutputType = Display.HdrCapabilities.HDR_TYPE_INVALID;
305 
306 
307     // The synchronization root for the display manager.
308     // This lock guards most of the display manager's state.
309     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
310     // into WindowManagerService methods that require mWindowMap while holding this unless you are
311     // very very sure that no deadlock can occur.
312     private final SyncRoot mSyncRoot = new SyncRoot();
313 
314     // True if in safe mode.
315     // This option may disable certain display adapters.
316     public boolean mSafeMode;
317 
318     // All callback records indexed by calling process id.
319     private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>();
320 
321     /**
322      *  All {@link IVirtualDevice} and {@link DisplayWindowPolicyController}s indexed by
323      *  {@link DisplayInfo#displayId}.
324      */
325     final SparseArray<Pair<IVirtualDevice, DisplayWindowPolicyController>>
326             mDisplayWindowPolicyControllers = new SparseArray<>();
327 
328     /**
329      * Provides {@link HighBrightnessModeMetadata}s for {@link DisplayDevice}s.
330      */
331     private final HighBrightnessModeMetadataMapper mHighBrightnessModeMetadataMapper =
332             new HighBrightnessModeMetadataMapper();
333 
334     // List of all currently registered display adapters.
335     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<>();
336 
337     /**
338      * Repository of all active {@link DisplayDevice}s.
339      */
340     private final DisplayDeviceRepository mDisplayDeviceRepo;
341 
342     /**
343      * Contains all the {@link LogicalDisplay} instances and is responsible for mapping
344      * {@link DisplayDevice}s to {@link LogicalDisplay}s. DisplayManagerService listens to display
345      * event on this object.
346      */
347     private final LogicalDisplayMapper mLogicalDisplayMapper;
348 
349     // List of all display transaction listeners.
350     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
351             new CopyOnWriteArrayList<>();
352 
353     /** List of all display group listeners. */
354     private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners =
355             new CopyOnWriteArrayList<>();
356 
357     /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
358     private final SparseArray<DisplayPowerControllerInterface> mDisplayPowerControllers =
359             new SparseArray<>();
360 
361     /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
362     private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
363         // Synchronized to avoid race conditions when updating multiple display states.
364         @Override
365         public synchronized void requestDisplayState(int displayId, int state, float brightness,
366                 float sdrBrightness) {
367             boolean allInactive = true;
368             boolean allOff = true;
369             final boolean stateChanged;
370             synchronized (mSyncRoot) {
371                 final int index = mDisplayStates.indexOfKey(displayId);
372                 if (index > -1) {
373                     final int currentState = mDisplayStates.valueAt(index);
374                     stateChanged = state != currentState;
375                     if (stateChanged) {
376                         final int size = mDisplayStates.size();
377                         for (int i = 0; i < size; i++) {
378                             final int displayState = i == index ? state : mDisplayStates.valueAt(i);
379                             if (displayState != Display.STATE_OFF) {
380                                 allOff = false;
381                             }
382                             if (Display.isActiveState(displayState)) {
383                                 allInactive = false;
384                             }
385                             if (!allOff && !allInactive) {
386                                 break;
387                             }
388                         }
389                     }
390                 } else {
391                     stateChanged = false;
392                 }
393             }
394 
395             // The order of operations is important for legacy reasons.
396             if (state == Display.STATE_OFF) {
397                 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
398             }
399 
400             if (stateChanged) {
401                 mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff);
402             }
403 
404             if (state != Display.STATE_OFF) {
405                 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness);
406             }
407         }
408     };
409 
410     /**
411      * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display
412      * state.
413      */
414     private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;
415 
416     /** The {@link Handler} used by all {@link DisplayPowerController}s. */
417     private Handler mPowerHandler;
418 
419     // A map from LogicalDisplay ID to display power state.
420     @GuardedBy("mSyncRoot")
421     private final SparseIntArray mDisplayStates = new SparseIntArray();
422 
423     // A map from LogicalDisplay ID to display brightness.
424     @GuardedBy("mSyncRoot")
425     private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>();
426 
427     // Set to true when there are pending display changes that have yet to be applied
428     // to the surface flinger state.
429     private boolean mPendingTraversal;
430 
431     // The Wifi display adapter, or null if not registered.
432     private WifiDisplayAdapter mWifiDisplayAdapter;
433 
434     // The number of active wifi display scan requests.
435     private int mWifiDisplayScanRequestCount;
436 
437     // The virtual display adapter, or null if not registered.
438     private VirtualDisplayAdapter mVirtualDisplayAdapter;
439 
440     // The User ID of the current user
441     private @UserIdInt int mCurrentUserId;
442 
443     // The stable device screen height and width. These are not tied to a specific display, even
444     // the default display, because they need to be stable over the course of the device's entire
445     // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
446     // device).
447     private Point mStableDisplaySize = new Point();
448 
449     // Whether the system has finished booting or not.
450     private boolean mSystemReady;
451 
452     // The top inset of the default display.
453     // This gets persisted so that the boot animation knows how to transition from the display's
454     // full size to the size configured by the user. Right now we only persist and animate the top
455     // inset, but theoretically we could do it for all of them.
456     private int mDefaultDisplayTopInset;
457 
458     // Viewports of the default display and the display that should receive touch
459     // input from an external source.  Used by the input system.
460     @GuardedBy("mSyncRoot")
461     private final ArrayList<DisplayViewport> mViewports = new ArrayList<>();
462 
463     // Persistent data store for all internal settings maintained by the display manager service.
464     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
465 
466     // Temporary callback list, used when sending display events to applications.
467     // May be used outside of the lock but only on the handler thread.
468     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<>();
469 
470     // Pending callback records indexed by calling process uid and pid.
471     // Must be used outside of the lock mSyncRoot and should be self-locked.
472     @GuardedBy("mPendingCallbackSelfLocked")
473     private final SparseArray<SparseArray<PendingCallback>> mPendingCallbackSelfLocked =
474             new SparseArray<>();
475 
476     // Temporary viewports, used when sending new viewport information to the
477     // input system.  May be used outside of the lock but only on the handler thread.
478     private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>();
479 
480     // The default color mode for default displays. Overrides the usual
481     // Display.Display.COLOR_MODE_DEFAULT for local displays.
482     private final int mDefaultDisplayDefaultColorMode;
483 
484     // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
485     private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
486 
487     private final Injector mInjector;
488 
489     // The minimum brightness curve, which guarantess that any brightness curve that dips below it
490     // is rejected by the system.
491     private final Curve mMinimumBrightnessCurve;
492     private final Spline mMinimumBrightnessSpline;
493     private final ColorSpace mWideColorSpace;
494     private final OverlayProperties mOverlayProperties;
495 
496     private SensorManager mSensorManager;
497     private BrightnessTracker mBrightnessTracker;
498 
499     private SmallAreaDetectionController mSmallAreaDetectionController;
500 
501 
502     // Whether minimal post processing is allowed by the user.
503     @GuardedBy("mSyncRoot")
504     private boolean mMinimalPostProcessingAllowed;
505 
506     // Receives notifications about changes to Settings.
507     private SettingsObserver mSettingsObserver;
508 
509     // Keeps note of what state the device is in, used for idle screen brightness mode.
510     private boolean mIsDocked;
511     private boolean mIsDreaming;
512 
513     private boolean mBootCompleted = false;
514 
515     // If we would like to keep a particular eye on a package, we can set the package name.
516     private final boolean mExtraDisplayEventLogging;
517     private final String mExtraDisplayLoggingPackageName;
518 
519     private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() {
520         @Override
521         public void onReceive(Context context, Intent intent) {
522             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
523                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
524                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
525                 mIsDocked = dockState == Intent.EXTRA_DOCK_STATE_DESK
526                         || dockState == Intent.EXTRA_DOCK_STATE_LE_DESK
527                         || dockState == Intent.EXTRA_DOCK_STATE_HE_DESK;
528             }
529             if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) {
530                 mIsDreaming = true;
531             } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) {
532                 mIsDreaming = false;
533             }
534             setDockedAndIdleEnabled(/* enabled= */(mIsDocked && mIsDreaming),
535                     Display.DEFAULT_DISPLAY);
536         }
537     };
538 
539     private final BroadcastReceiver mResolutionRestoreReceiver = new BroadcastReceiver() {
540         @Override
541         public void onReceive(Context context, Intent intent) {
542             if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) {
543                 if (Settings.Secure.SCREEN_RESOLUTION_MODE.equals(
544                         intent.getExtra(Intent.EXTRA_SETTING_NAME))) {
545                     restoreResolutionFromBackup();
546                 }
547             }
548         }
549     };
550 
551     private final DisplayModeDirector.DisplayDeviceConfigProvider mDisplayDeviceConfigProvider =
552             displayId -> {
553                 synchronized (mSyncRoot) {
554                     final DisplayDevice device = getDeviceForDisplayLocked(displayId);
555                     if (device == null) {
556                         return null;
557                     }
558                     return device.getDisplayDeviceConfig();
559                 }
560             };
561 
562     private final BrightnessSynchronizer mBrightnessSynchronizer;
563 
564     private final DeviceConfigParameterProvider mConfigParameterProvider;
565 
566     private final DisplayManagerFlags mFlags;
567 
568     private final DisplayNotificationManager mDisplayNotificationManager;
569     private final ExternalDisplayStatsService mExternalDisplayStatsService;
570 
571     /**
572      * Applications use {@link android.view.Display#getRefreshRate} and
573      * {@link android.view.Display.Mode#getRefreshRate} to know what is the display refresh rate.
574      * Starting with Android S, the platform might throttle down applications frame rate to a
575      * divisor of the refresh rate if it is more preferable (for example if the application called
576      * to {@link android.view.Surface#setFrameRate}).
577      * Applications will experience {@link android.view.Choreographer#postFrameCallback} callbacks
578      * and backpressure at the throttled frame rate.
579      *
580      * {@link android.view.Display#getRefreshRate} will always return the application frame rate
581      * and not the physical display refresh rate to allow applications to do frame pacing correctly.
582      *
583      * {@link android.view.Display.Mode#getRefreshRate} will return the application frame rate if
584      * compiled to a previous release and starting with Android S it will return the physical
585      * display refresh rate.
586      */
587     @ChangeId
588     @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
589     static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE = 170503758L;
590 
DisplayManagerService(Context context)591     public DisplayManagerService(Context context) {
592         this(context, new Injector());
593     }
594 
595     @VisibleForTesting
DisplayManagerService(Context context, Injector injector)596     DisplayManagerService(Context context, Injector injector) {
597         super(context);
598         FoldSettingProvider foldSettingProvider = new FoldSettingProvider(context,
599                 new SettingsWrapper(),
600                 new FoldLockSettingAvailabilityProvider(context.getResources()));
601         mInjector = injector;
602         mContext = context;
603         mFlags = injector.getFlags();
604         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
605         mUiHandler = UiThread.getHandler();
606         mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
607         mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
608                 foldSettingProvider, new FoldGracePeriodProvider(),
609                 mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags);
610         mDisplayModeDirector = new DisplayModeDirector(
611                 context, mHandler, mFlags, mDisplayDeviceConfigProvider);
612         mBrightnessSynchronizer = new BrightnessSynchronizer(mContext,
613                 mFlags.isBrightnessIntRangeUserPerceptionEnabled());
614         Resources resources = mContext.getResources();
615         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
616                 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
617         mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);
618         mDefaultHdrConversionMode = mContext.getResources().getBoolean(
619                 com.android.internal.R.bool.config_enableDefaultHdrConversionPassthrough)
620                         ? HdrConversionMode.HDR_CONVERSION_PASSTHROUGH
621                         : HdrConversionMode.HDR_CONVERSION_SYSTEM;
622         float[] lux = getFloatArray(resources.obtainTypedArray(
623                 com.android.internal.R.array.config_minimumBrightnessCurveLux));
624         float[] nits = getFloatArray(resources.obtainTypedArray(
625                 com.android.internal.R.array.config_minimumBrightnessCurveNits));
626         mMinimumBrightnessCurve = new Curve(lux, nits);
627         mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
628 
629         mCurrentUserId = UserHandle.USER_SYSTEM;
630         ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
631         mWideColorSpace = colorSpaces[1];
632         mOverlayProperties = SurfaceControl.getOverlaySupport();
633         mSystemReady = false;
634         mConfigParameterProvider = new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
635         mExtraDisplayLoggingPackageName = DisplayProperties.debug_vri_package().orElse(null);
636         mExtraDisplayEventLogging = !TextUtils.isEmpty(mExtraDisplayLoggingPackageName);
637 
638         mExternalDisplayStatsService = new ExternalDisplayStatsService(mContext, mHandler);
639         mDisplayNotificationManager = new DisplayNotificationManager(mFlags, mContext,
640                 mExternalDisplayStatsService);
641         mExternalDisplayPolicy = new ExternalDisplayPolicy(new ExternalDisplayPolicyInjector());
642     }
643 
setupSchedulerPolicies()644     public void setupSchedulerPolicies() {
645         // android.display and android.anim is critical to user experience and we should make sure
646         // it is not in the default foregroup groups, add it to top-app to make sure it uses all
647         // the cores and scheduling settings for top-app when it runs.
648         Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
649                 Process.THREAD_GROUP_TOP_APP);
650         Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
651                 Process.THREAD_GROUP_TOP_APP);
652         Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
653                 Process.THREAD_GROUP_TOP_APP);
654     }
655 
656     @Override
onStart()657     public void onStart() {
658         // We need to pre-load the persistent data store so it's ready before the default display
659         // adapter is up so that we have it's configuration. We could load it lazily, but since
660         // we're going to have to read it in eventually we may as well do it here rather than after
661         // we've waited for the display to register itself with us.
662         synchronized (mSyncRoot) {
663             mPersistentDataStore.loadIfNeeded();
664             loadStableDisplayValuesLocked();
665         }
666         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
667 
668         // If there was a runtime restart then we may have stale caches left around, so we need to
669         // make sure to invalidate them upon every start.
670         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
671 
672         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
673                 true /*allowIsolated*/, DUMP_FLAG_PRIORITY_CRITICAL);
674         publishLocalService(DisplayManagerInternal.class, new LocalService());
675     }
676 
677     @Override
onBootPhase(int phase)678     public void onBootPhase(int phase) {
679         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
680             synchronized (mSyncRoot) {
681                 long timeout = SystemClock.uptimeMillis()
682                         + mInjector.getDefaultDisplayDelayTimeout();
683                 while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null
684                         || mVirtualDisplayAdapter == null) {
685                     long delay = timeout - SystemClock.uptimeMillis();
686                     if (delay <= 0) {
687                         throw new RuntimeException("Timeout waiting for default display "
688                                 + "to be initialized. DefaultDisplay="
689                                 + mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)
690                                 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
691                     }
692                     if (DEBUG) {
693                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
694                     }
695                     try {
696                         mSyncRoot.wait(delay);
697                     } catch (InterruptedException ex) {
698                     }
699                 }
700             }
701         } else if (phase == PHASE_BOOT_COMPLETED) {
702             synchronized (mSyncRoot) {
703                 mBootCompleted = true;
704                 for (int i = 0; i < mDisplayPowerControllers.size(); i++) {
705                     mDisplayPowerControllers.valueAt(i).onBootCompleted();
706                 }
707             }
708             mDisplayModeDirector.onBootCompleted();
709             mLogicalDisplayMapper.onBootCompleted();
710             mDisplayNotificationManager.onBootCompleted();
711             mExternalDisplayPolicy.onBootCompleted();
712         }
713     }
714 
715     @Override
onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)716     public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
717         final int newUserId = to.getUserIdentifier();
718         final int userSerial = getUserManager().getUserSerialNumber(newUserId);
719         synchronized (mSyncRoot) {
720             boolean userSwitching = mCurrentUserId != newUserId;
721             if (userSwitching) {
722                 mCurrentUserId = newUserId;
723             }
724             mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
725                 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
726                     return;
727                 }
728                 final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
729                         logicalDisplay.getDisplayIdLocked());
730                 if (dpc == null) {
731                     return;
732                 }
733                 if (userSwitching) {
734                     BrightnessConfiguration config =
735                             getBrightnessConfigForDisplayWithPdsFallbackLocked(
736                             logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(),
737                             userSerial);
738                     dpc.setBrightnessConfiguration(config, /* shouldResetShortTermModel= */ true);
739                 }
740                 final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked();
741                 float newBrightness = device == null ? PowerManager.BRIGHTNESS_INVALID_FLOAT
742                         : mPersistentDataStore.getBrightness(device, userSerial);
743                 if (Float.isNaN(newBrightness)) {
744                     newBrightness = logicalDisplay.getDisplayInfoLocked().brightnessDefault;
745                 }
746                 dpc.onSwitchUser(newUserId, userSerial, newBrightness);
747             });
748             handleSettingsChange();
749         }
750     }
751 
752     /**
753      * The 2nd stage initialization
754      * TODO: Use dependencies or a boot phase
755      */
756     @SuppressLint("AndroidFrameworkRequiresPermission")
windowManagerAndInputReady()757     public void windowManagerAndInputReady() {
758         synchronized (mSyncRoot) {
759             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
760             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
761             mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
762             ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
763             activityManager.addOnUidImportanceListener(mUidImportanceListener, IMPORTANCE_CACHED);
764 
765             mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class);
766             mContext.getSystemService(DeviceStateManager.class).registerCallback(
767                     new HandlerExecutor(mHandler), new DeviceStateListener());
768 
769             mLogicalDisplayMapper.onWindowManagerReady();
770             scheduleTraversalLocked(false);
771         }
772     }
773 
774     /**
775      * Called when the system is ready to go.
776      */
systemReady(boolean safeMode)777     public void systemReady(boolean safeMode) {
778         synchronized (mSyncRoot) {
779             mSafeMode = safeMode;
780             mSystemReady = true;
781             mIsHdrOutputControlEnabled =
782                     mConfigParameterProvider.isHdrOutputControlFeatureEnabled();
783             mConfigParameterProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(),
784                     properties -> mIsHdrOutputControlEnabled =
785                             mConfigParameterProvider.isHdrOutputControlFeatureEnabled());
786             // Just in case the top inset changed before the system was ready. At this point, any
787             // relevant configuration should be in place.
788             recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
789 
790             updateSettingsLocked();
791             updateUserDisabledHdrTypesFromSettingsLocked();
792             updateUserPreferredDisplayModeSettingsLocked();
793             if (mIsHdrOutputControlEnabled) {
794                 updateHdrConversionModeSettingsLocked();
795             }
796         }
797 
798         mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
799                 new DesiredDisplayModeSpecsObserver());
800         mDisplayModeDirector.start(mSensorManager);
801 
802         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
803 
804         mSettingsObserver = new SettingsObserver();
805 
806         mBrightnessSynchronizer.startSynchronizing();
807 
808         final IntentFilter filter = new IntentFilter();
809         filter.addAction(Intent.ACTION_DREAMING_STARTED);
810         filter.addAction(Intent.ACTION_DREAMING_STOPPED);
811         filter.addAction(Intent.ACTION_DOCK_EVENT);
812 
813         mContext.registerReceiver(mIdleModeReceiver, filter);
814 
815         if (mFlags.isResolutionBackupRestoreEnabled()) {
816             final IntentFilter restoreFilter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
817             mContext.registerReceiver(mResolutionRestoreReceiver, restoreFilter);
818         }
819 
820         mSmallAreaDetectionController = (mFlags.isSmallAreaDetectionEnabled())
821                 ? SmallAreaDetectionController.create(mContext) : null;
822     }
823 
824     @VisibleForTesting
getDisplayHandler()825     Handler getDisplayHandler() {
826         return mHandler;
827     }
828 
829     @VisibleForTesting
getDisplayDeviceRepository()830     DisplayDeviceRepository getDisplayDeviceRepository() {
831         return mDisplayDeviceRepo;
832     }
833 
834     @VisibleForTesting
getLogicalDisplayMapper()835     LogicalDisplayMapper getLogicalDisplayMapper() {
836         return mLogicalDisplayMapper;
837     }
838 
839     @VisibleForTesting
isMinimalPostProcessingAllowed()840     boolean isMinimalPostProcessingAllowed() {
841         synchronized (mSyncRoot) {
842             return mMinimalPostProcessingAllowed;
843         }
844     }
845 
846     @VisibleForTesting
setMinimalPostProcessingAllowed(boolean allowed)847     void setMinimalPostProcessingAllowed(boolean allowed) {
848         synchronized (mSyncRoot) {
849             mMinimalPostProcessingAllowed = allowed;
850         }
851     }
852 
getDisplayNotificationManager()853     DisplayNotificationManager getDisplayNotificationManager() {
854         return mDisplayNotificationManager;
855     }
856 
loadStableDisplayValuesLocked()857     private void loadStableDisplayValuesLocked() {
858         final Point size = mPersistentDataStore.getStableDisplaySize();
859         if (size.x > 0 && size.y > 0) {
860             // Just set these values directly so we don't write the display persistent data again
861             // unnecessarily
862             mStableDisplaySize.set(size.x, size.y);
863         } else {
864             final Resources res = mContext.getResources();
865             final int width = res.getInteger(
866                     com.android.internal.R.integer.config_stableDeviceDisplayWidth);
867             final int height = res.getInteger(
868                     com.android.internal.R.integer.config_stableDeviceDisplayHeight);
869             if (width > 0 && height > 0) {
870                 setStableDisplaySizeLocked(width, height);
871             }
872         }
873     }
874 
getStableDisplaySizeInternal()875     private Point getStableDisplaySizeInternal() {
876         Point r = new Point();
877         synchronized (mSyncRoot) {
878             if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
879                 r.set(mStableDisplaySize.x, mStableDisplaySize.y);
880             }
881         }
882         return r;
883     }
884 
registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)885     private void registerDisplayTransactionListenerInternal(
886             DisplayTransactionListener listener) {
887         // List is self-synchronized copy-on-write.
888         mDisplayTransactionListeners.add(listener);
889     }
890 
unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)891     private void unregisterDisplayTransactionListenerInternal(
892             DisplayTransactionListener listener) {
893         // List is self-synchronized copy-on-write.
894         mDisplayTransactionListeners.remove(listener);
895     }
896 
897     @VisibleForTesting
setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info)898     void setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info) {
899         synchronized (mSyncRoot) {
900             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
901             if (display != null) {
902                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
903                     handleLogicalDisplayChangedLocked(display);
904                 }
905             }
906         }
907     }
908 
909     /**
910      * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
911      */
getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)912     private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
913         synchronized (mSyncRoot) {
914             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
915             if (display != null) {
916                 display.getNonOverrideDisplayInfoLocked(outInfo);
917             }
918         }
919     }
920 
921     @VisibleForTesting
performTraversalInternal(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)922     void performTraversalInternal(SurfaceControl.Transaction t,
923             SparseArray<SurfaceControl.Transaction> displayTransactions) {
924         synchronized (mSyncRoot) {
925             if (!mPendingTraversal) {
926                 return;
927             }
928             mPendingTraversal = false;
929 
930             performTraversalLocked(t, displayTransactions);
931         }
932 
933         // List is self-synchronized copy-on-write.
934         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
935             listener.onDisplayTransaction(t);
936         }
937     }
938 
clampBrightness(int displayState, float brightnessState)939     private float clampBrightness(int displayState, float brightnessState) {
940         if (displayState == Display.STATE_OFF) {
941             brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT;
942         } else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT
943                 && brightnessState < PowerManager.BRIGHTNESS_MIN) {
944             brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
945         } else if (brightnessState > PowerManager.BRIGHTNESS_MAX) {
946             brightnessState = PowerManager.BRIGHTNESS_MAX;
947         }
948         return brightnessState;
949     }
950 
requestDisplayStateInternal(int displayId, int state, float brightnessState, float sdrBrightnessState)951     private void requestDisplayStateInternal(int displayId, int state, float brightnessState,
952             float sdrBrightnessState) {
953         if (state == Display.STATE_UNKNOWN) {
954             state = Display.STATE_ON;
955         }
956 
957         brightnessState = clampBrightness(state, brightnessState);
958         sdrBrightnessState = clampBrightness(state, sdrBrightnessState);
959 
960         // Update the display state within the lock.
961         // Note that we do not need to schedule traversals here although it
962         // may happen as a side-effect of displays changing state.
963         final Runnable runnable;
964         final String traceMessage;
965         synchronized (mSyncRoot) {
966             final int index = mDisplayStates.indexOfKey(displayId);
967 
968             final BrightnessPair brightnessPair =
969                     index < 0 ? null : mDisplayBrightnesses.valueAt(index);
970             if (index < 0 || (mDisplayStates.valueAt(index) == state
971                     && brightnessPair.brightness == brightnessState
972                     && brightnessPair.sdrBrightness == sdrBrightnessState)) {
973                 return; // Display no longer exists or no change.
974             }
975 
976             if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
977                 traceMessage = Display.stateToString(state)
978                            + ", brightness=" + brightnessState
979                            + ", sdrBrightness=" + sdrBrightnessState;
980                 Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_POWER,
981                         "requestDisplayStateInternal:" + displayId,
982                         traceMessage, displayId);
983             }
984 
985             mDisplayStates.setValueAt(index, state);
986             brightnessPair.brightness = brightnessState;
987             brightnessPair.sdrBrightness = sdrBrightnessState;
988             // TODO(b/297503094) Preventing disabled display from being turned on should happen
989             // elsewhere.
990             LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
991             if (!display.isEnabledLocked() && state != Display.STATE_OFF) {
992                 // If the display is disabled, any request other than turning it off should fail.
993                 return;
994             }
995             runnable = updateDisplayStateLocked(display.getPrimaryDisplayDeviceLocked());
996             if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
997                 Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_POWER,
998                         "requestDisplayStateInternal:" + displayId, displayId);
999             }
1000         }
1001 
1002         // Setting the display power state can take hundreds of milliseconds
1003         // to complete so we defer the most expensive part of the work until
1004         // after we have exited the critical section to avoid blocking other
1005         // threads for a long time.
1006         if (runnable != null) {
1007             runnable.run();
1008         }
1009     }
1010 
1011     private class UidImportanceListener implements ActivityManager.OnUidImportanceListener {
1012         @Override
1013         public void onUidImportance(int uid, int importance) {
1014             synchronized (mPendingCallbackSelfLocked) {
1015                 if (importance >= IMPORTANCE_GONE) {
1016                     // Clean up as the app is already gone
1017                     Slog.d(TAG, "Drop pending events for gone uid " + uid);
1018                     mPendingCallbackSelfLocked.delete(uid);
1019                     return;
1020                 } else if (importance >= IMPORTANCE_CACHED) {
1021                     // Nothing to do as the app is still in cached mode
1022                     return;
1023                 }
1024 
1025                 // Do we care about this uid?
1026                 SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(uid);
1027                 if (pendingCallbacks == null) {
1028                     return;
1029                 }
1030 
1031                 // Send the pending events out when a certain uid becomes non-cached
1032                 if (DEBUG) {
1033                     Slog.d(TAG, "Uid " + uid + " becomes " + importance);
1034                 }
1035                 for (int i = 0; i < pendingCallbacks.size(); i++) {
1036                     PendingCallback pendingCallback = pendingCallbacks.valueAt(i);
1037                     if (pendingCallback != null) {
1038                         pendingCallback.sendPendingDisplayEvent();
1039                     }
1040                 }
1041                 mPendingCallbackSelfLocked.delete(uid);
1042             }
1043         }
1044     }
1045 
1046     private class SettingsObserver extends ContentObserver {
SettingsObserver()1047         SettingsObserver() {
1048             super(mHandler);
1049 
1050             mContext.getContentResolver().registerContentObserver(
1051                     Settings.Secure.getUriFor(
1052                         Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED), false, this);
1053         }
1054 
1055         @Override
onChange(boolean selfChange, Uri uri)1056         public void onChange(boolean selfChange, Uri uri) {
1057             handleSettingsChange();
1058         }
1059     }
1060 
handleSettingsChange()1061     private void handleSettingsChange() {
1062         synchronized (mSyncRoot) {
1063             updateSettingsLocked();
1064             scheduleTraversalLocked(false);
1065         }
1066     }
1067 
updateSettingsLocked()1068     private void updateSettingsLocked() {
1069         setMinimalPostProcessingAllowed(Settings.Secure.getIntForUser(
1070                 mContext.getContentResolver(), Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
1071                 1, UserHandle.USER_CURRENT) != 0);
1072     }
1073 
restoreResolutionFromBackup()1074     private void restoreResolutionFromBackup() {
1075         int savedMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
1076                 Settings.Secure.SCREEN_RESOLUTION_MODE,
1077                 RESOLUTION_MODE_UNKNOWN, UserHandle.USER_CURRENT);
1078         if (savedMode == RESOLUTION_MODE_UNKNOWN) {
1079             // Nothing to restore.
1080             return;
1081         }
1082 
1083         synchronized (mSyncRoot) {
1084             LogicalDisplay display =
1085                     mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY);
1086             DisplayDevice device = display == null ? null : display.getPrimaryDisplayDeviceLocked();
1087             if (device == null) {
1088                 Slog.w(TAG, "No default display device present to restore resolution mode");
1089                 return;
1090             }
1091 
1092             Point[] supportedRes = device.getSupportedResolutionsLocked();
1093             if (supportedRes.length != 2) {
1094                 if (DEBUG) {
1095                     Slog.d(TAG, "Skipping resolution restore - " + supportedRes.length);
1096                 }
1097                 return;
1098             }
1099 
1100             // We follow the same logic as Settings but in reverse. If the display supports 2
1101             // resolutions, we treat the small (index=0) one as HIGH and the larger (index=1)
1102             // one as FULL and restore the correct resolution accordingly.
1103             int index = savedMode == RESOLUTION_MODE_HIGH ? 0 : 1;
1104             Point res = supportedRes[index];
1105             Display.Mode newMode = new Display.Mode(res.x, res.y, /*refreshRate=*/ 0);
1106             Slog.i(TAG, "Restoring resolution from backup: (" + savedMode + ") "
1107                     + res.x + "x" + res.y);
1108             setUserPreferredDisplayModeInternal(Display.DEFAULT_DISPLAY, newMode);
1109         }
1110     }
1111 
updateUserDisabledHdrTypesFromSettingsLocked()1112     private void updateUserDisabledHdrTypesFromSettingsLocked() {
1113         mAreUserDisabledHdrTypesAllowed = (Settings.Global.getInt(
1114                 mContext.getContentResolver(),
1115                 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
1116                 1) != 0);
1117 
1118         String userDisabledHdrTypes = Settings.Global.getString(mContext.getContentResolver(),
1119                 Settings.Global.USER_DISABLED_HDR_FORMATS);
1120 
1121         if (userDisabledHdrTypes != null) {
1122             try {
1123                 String[] userDisabledHdrTypeStrings =
1124                         TextUtils.split(userDisabledHdrTypes, ",");
1125                 mUserDisabledHdrTypes = new int[userDisabledHdrTypeStrings.length];
1126                 for (int i = 0; i < userDisabledHdrTypeStrings.length; i++) {
1127                     mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
1128                 }
1129 
1130                 if (!mAreUserDisabledHdrTypesAllowed) {
1131                     mLogicalDisplayMapper.forEachLocked(
1132                             display -> {
1133                                 display.setUserDisabledHdrTypes(mUserDisabledHdrTypes);
1134                                 handleLogicalDisplayChangedLocked(display);
1135                             });
1136                 }
1137 
1138             } catch (NumberFormatException e) {
1139                 Slog.e(TAG, "Failed to parse USER_DISABLED_HDR_FORMATS. "
1140                         + "Clearing the setting.", e);
1141                 clearUserDisabledHdrTypesLocked();
1142             }
1143         } else {
1144             clearUserDisabledHdrTypesLocked();
1145         }
1146     }
1147 
clearUserDisabledHdrTypesLocked()1148     private void clearUserDisabledHdrTypesLocked() {
1149         synchronized (mSyncRoot) {
1150             mUserDisabledHdrTypes = new int[]{};
1151             Settings.Global.putString(mContext.getContentResolver(),
1152                     Settings.Global.USER_DISABLED_HDR_FORMATS, "");
1153         }
1154     }
1155 
updateUserPreferredDisplayModeSettingsLocked()1156     private void updateUserPreferredDisplayModeSettingsLocked() {
1157         final float refreshRate = Settings.Global.getFloat(mContext.getContentResolver(),
1158                 Settings.Global.USER_PREFERRED_REFRESH_RATE, Display.INVALID_DISPLAY_REFRESH_RATE);
1159         final int height = Settings.Global.getInt(mContext.getContentResolver(),
1160                 Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, Display.INVALID_DISPLAY_HEIGHT);
1161         final int width = Settings.Global.getInt(mContext.getContentResolver(),
1162                 Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, Display.INVALID_DISPLAY_WIDTH);
1163         Display.Mode mode = new Display.Mode(width, height, refreshRate);
1164         mUserPreferredMode = isResolutionAndRefreshRateValid(mode) ? mode : null;
1165         if (mUserPreferredMode != null) {
1166             mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
1167                 device.setUserPreferredDisplayModeLocked(mode);
1168             });
1169         } else {
1170             mLogicalDisplayMapper.forEachLocked(this::configurePreferredDisplayModeLocked);
1171         }
1172     }
1173 
getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[] frameRateOverrides, DisplayInfo info, int callingUid)1174     private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
1175             frameRateOverrides, DisplayInfo info, int callingUid) {
1176         float frameRateHz = info.renderFrameRate;
1177         for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) {
1178             if (frameRateOverride.uid == callingUid) {
1179                 frameRateHz = frameRateOverride.frameRateHz;
1180                 break;
1181             }
1182         }
1183 
1184         if (frameRateHz == 0) {
1185             return info;
1186         }
1187 
1188         // For non-apps users we always return the physical refresh rate from display mode
1189         boolean displayModeReturnsPhysicalRefreshRate =
1190                 callingUid < FIRST_APPLICATION_UID
1191                         || CompatChanges.isChangeEnabled(
1192                                 DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE, callingUid);
1193 
1194         // Override the refresh rate only if it is a divisor of the current
1195         // refresh rate. This calculation needs to be in sync with the native code
1196         // in RefreshRateSelector::getFrameRateDivisor
1197         Display.Mode currentMode = info.getMode();
1198         float numPeriods = currentMode.getRefreshRate() / frameRateHz;
1199         float numPeriodsRound = Math.round(numPeriods);
1200         if (Math.abs(numPeriods - numPeriodsRound) > THRESHOLD_FOR_REFRESH_RATES_DIVISORS) {
1201             return info;
1202         }
1203         frameRateHz = currentMode.getRefreshRate() / numPeriodsRound;
1204 
1205         DisplayInfo overriddenInfo = new DisplayInfo();
1206         overriddenInfo.copyFrom(info);
1207         for (Display.Mode mode : info.supportedModes) {
1208             if (!mode.equalsExceptRefreshRate(currentMode)) {
1209                 continue;
1210             }
1211 
1212             if (mode.getRefreshRate() >= frameRateHz - THRESHOLD_FOR_REFRESH_RATES_DIVISORS
1213                     && mode.getRefreshRate()
1214                     <= frameRateHz + THRESHOLD_FOR_REFRESH_RATES_DIVISORS) {
1215                 if (DEBUG) {
1216                     Slog.d(TAG, "found matching modeId " + mode.getModeId());
1217                 }
1218                 overriddenInfo.refreshRateOverride = mode.getRefreshRate();
1219 
1220                 if (!displayModeReturnsPhysicalRefreshRate) {
1221                     overriddenInfo.modeId = mode.getModeId();
1222                 }
1223                 return overriddenInfo;
1224             }
1225         }
1226 
1227         overriddenInfo.refreshRateOverride = frameRateHz;
1228         if (!displayModeReturnsPhysicalRefreshRate) {
1229             overriddenInfo.supportedModes = Arrays.copyOf(info.supportedModes,
1230                     info.supportedModes.length + 1);
1231             overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] =
1232                     new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE,
1233                             currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(),
1234                             overriddenInfo.refreshRateOverride,
1235                             currentMode.getVsyncRate(),
1236                             new float[0], currentMode.getSupportedHdrTypes());
1237             overriddenInfo.modeId =
1238                     overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1]
1239                             .getModeId();
1240         }
1241         return overriddenInfo;
1242     }
1243 
getDisplayInfoInternal(int displayId, int callingUid)1244     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
1245         synchronized (mSyncRoot) {
1246             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1247             if (display != null) {
1248                 final DisplayInfo info =
1249                         getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(),
1250                                 display.getDisplayInfoLocked(), callingUid);
1251                 if (info.hasAccess(callingUid)
1252                         || isUidPresentOnDisplayInternal(callingUid, displayId)) {
1253                     return info;
1254                 }
1255             }
1256             return null;
1257         }
1258     }
1259 
registerCallbackInternal(IDisplayManagerCallback callback, int callingPid, int callingUid, @EventsMask long eventsMask)1260     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid,
1261             int callingUid, @EventsMask long eventsMask) {
1262         synchronized (mSyncRoot) {
1263             CallbackRecord record = mCallbacks.get(callingPid);
1264 
1265             if (record != null) {
1266                 record.updateEventsMask(eventsMask);
1267                 return;
1268             }
1269 
1270             record = new CallbackRecord(callingPid, callingUid, callback, eventsMask);
1271             try {
1272                 IBinder binder = callback.asBinder();
1273                 binder.linkToDeath(record, 0);
1274             } catch (RemoteException ex) {
1275                 // give up
1276                 throw new RuntimeException(ex);
1277             }
1278 
1279             mCallbacks.put(callingPid, record);
1280         }
1281     }
1282 
onCallbackDied(CallbackRecord record)1283     private void onCallbackDied(CallbackRecord record) {
1284         synchronized (mSyncRoot) {
1285             mCallbacks.remove(record.mPid);
1286             stopWifiDisplayScanLocked(record);
1287         }
1288     }
1289 
startWifiDisplayScanInternal(int callingPid)1290     private void startWifiDisplayScanInternal(int callingPid) {
1291         synchronized (mSyncRoot) {
1292             CallbackRecord record = mCallbacks.get(callingPid);
1293             if (record == null) {
1294                 throw new IllegalStateException("The calling process has not "
1295                         + "registered an IDisplayManagerCallback.");
1296             }
1297             startWifiDisplayScanLocked(record);
1298         }
1299     }
1300 
startWifiDisplayScanLocked(CallbackRecord record)1301     private void startWifiDisplayScanLocked(CallbackRecord record) {
1302         if (!record.mWifiDisplayScanRequested) {
1303             record.mWifiDisplayScanRequested = true;
1304             if (mWifiDisplayScanRequestCount++ == 0) {
1305                 if (mWifiDisplayAdapter != null) {
1306                     mWifiDisplayAdapter.requestStartScanLocked();
1307                 }
1308             }
1309         }
1310     }
1311 
stopWifiDisplayScanInternal(int callingPid)1312     private void stopWifiDisplayScanInternal(int callingPid) {
1313         synchronized (mSyncRoot) {
1314             CallbackRecord record = mCallbacks.get(callingPid);
1315             if (record == null) {
1316                 throw new IllegalStateException("The calling process has not "
1317                         + "registered an IDisplayManagerCallback.");
1318             }
1319             stopWifiDisplayScanLocked(record);
1320         }
1321     }
1322 
stopWifiDisplayScanLocked(CallbackRecord record)1323     private void stopWifiDisplayScanLocked(CallbackRecord record) {
1324         if (record.mWifiDisplayScanRequested) {
1325             record.mWifiDisplayScanRequested = false;
1326             if (--mWifiDisplayScanRequestCount == 0) {
1327                 if (mWifiDisplayAdapter != null) {
1328                     mWifiDisplayAdapter.requestStopScanLocked();
1329                 }
1330             } else if (mWifiDisplayScanRequestCount < 0) {
1331                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
1332                         + mWifiDisplayScanRequestCount);
1333                 mWifiDisplayScanRequestCount = 0;
1334             }
1335         }
1336     }
1337 
connectWifiDisplayInternal(String address)1338     private void connectWifiDisplayInternal(String address) {
1339         synchronized (mSyncRoot) {
1340             if (mWifiDisplayAdapter != null) {
1341                 mWifiDisplayAdapter.requestConnectLocked(address);
1342             }
1343         }
1344     }
1345 
pauseWifiDisplayInternal()1346     private void pauseWifiDisplayInternal() {
1347         synchronized (mSyncRoot) {
1348             if (mWifiDisplayAdapter != null) {
1349                 mWifiDisplayAdapter.requestPauseLocked();
1350             }
1351         }
1352     }
1353 
resumeWifiDisplayInternal()1354     private void resumeWifiDisplayInternal() {
1355         synchronized (mSyncRoot) {
1356             if (mWifiDisplayAdapter != null) {
1357                 mWifiDisplayAdapter.requestResumeLocked();
1358             }
1359         }
1360     }
1361 
disconnectWifiDisplayInternal()1362     private void disconnectWifiDisplayInternal() {
1363         synchronized (mSyncRoot) {
1364             if (mWifiDisplayAdapter != null) {
1365                 mWifiDisplayAdapter.requestDisconnectLocked();
1366             }
1367         }
1368     }
1369 
renameWifiDisplayInternal(String address, String alias)1370     private void renameWifiDisplayInternal(String address, String alias) {
1371         synchronized (mSyncRoot) {
1372             if (mWifiDisplayAdapter != null) {
1373                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
1374             }
1375         }
1376     }
1377 
forgetWifiDisplayInternal(String address)1378     private void forgetWifiDisplayInternal(String address) {
1379         synchronized (mSyncRoot) {
1380             if (mWifiDisplayAdapter != null) {
1381                 mWifiDisplayAdapter.requestForgetLocked(address);
1382             }
1383         }
1384     }
1385 
getWifiDisplayStatusInternal()1386     private WifiDisplayStatus getWifiDisplayStatusInternal() {
1387         synchronized (mSyncRoot) {
1388             if (mWifiDisplayAdapter != null) {
1389                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
1390             }
1391             return new WifiDisplayStatus();
1392         }
1393     }
1394 
setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes)1395     private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) {
1396         synchronized (mSyncRoot) {
1397             if (userDisabledHdrTypes == null) {
1398                 Slog.e(TAG, "Null is not an expected argument to "
1399                         + "setUserDisabledHdrTypesInternal");
1400                 return;
1401             }
1402 
1403             // Verify if userDisabledHdrTypes contains expected HDR types
1404             if (!isSubsetOf(Display.HdrCapabilities.HDR_TYPES, userDisabledHdrTypes)) {
1405                 Slog.e(TAG, "userDisabledHdrTypes contains unexpected types");
1406                 return;
1407             }
1408 
1409             Arrays.sort(userDisabledHdrTypes);
1410             if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) {
1411                 return;
1412             }
1413             String userDisabledFormatsString = "";
1414             if (userDisabledHdrTypes.length != 0) {
1415                 userDisabledFormatsString = TextUtils.join(",",
1416                         Arrays.stream(userDisabledHdrTypes).boxed().toArray());
1417             }
1418             Settings.Global.putString(mContext.getContentResolver(),
1419                     Settings.Global.USER_DISABLED_HDR_FORMATS, userDisabledFormatsString);
1420             mUserDisabledHdrTypes = userDisabledHdrTypes;
1421             if (!mAreUserDisabledHdrTypesAllowed) {
1422                 mLogicalDisplayMapper.forEachLocked(
1423                         display -> {
1424                             display.setUserDisabledHdrTypes(userDisabledHdrTypes);
1425                             handleLogicalDisplayChangedLocked(display);
1426                         });
1427             }
1428         }
1429     }
1430 
isSubsetOf(int[] sortedSuperset, int[] subset)1431     private boolean isSubsetOf(int[] sortedSuperset, int[] subset) {
1432         for (int i : subset) {
1433             if (Arrays.binarySearch(sortedSuperset, i) < 0) {
1434                 return false;
1435             }
1436         }
1437         return true;
1438     }
1439 
setAreUserDisabledHdrTypesAllowedInternal( boolean areUserDisabledHdrTypesAllowed)1440     private void setAreUserDisabledHdrTypesAllowedInternal(
1441             boolean areUserDisabledHdrTypesAllowed) {
1442         synchronized (mSyncRoot) {
1443             if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) {
1444                 return;
1445             }
1446             mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed;
1447             if (mUserDisabledHdrTypes.length == 0) {
1448                 return;
1449             }
1450             Settings.Global.putInt(mContext.getContentResolver(),
1451                     Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
1452                     areUserDisabledHdrTypesAllowed ? 1 : 0);
1453             int userDisabledHdrTypes[] = {};
1454             if (!mAreUserDisabledHdrTypesAllowed) {
1455                 userDisabledHdrTypes = mUserDisabledHdrTypes;
1456             }
1457             int[] finalUserDisabledHdrTypes = userDisabledHdrTypes;
1458             mLogicalDisplayMapper.forEachLocked(
1459                     display -> {
1460                         display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes);
1461                         handleLogicalDisplayChangedLocked(display);
1462                     });
1463         }
1464     }
1465 
requestColorModeInternal(int displayId, int colorMode)1466     private void requestColorModeInternal(int displayId, int colorMode) {
1467         synchronized (mSyncRoot) {
1468             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
1469             if (display != null &&
1470                     display.getRequestedColorModeLocked() != colorMode) {
1471                 display.setRequestedColorModeLocked(colorMode);
1472                 scheduleTraversalLocked(false);
1473             }
1474         }
1475     }
1476 
validatePackageName(int uid, String packageName)1477     private boolean validatePackageName(int uid, String packageName) {
1478         // Root doesn't have a package name.
1479         if (uid == ROOT_UID) {
1480             return true;
1481         }
1482         if (packageName != null) {
1483             String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1484             if (packageNames != null) {
1485                 for (String n : packageNames) {
1486                     if (n.equals(packageName)) {
1487                         return true;
1488                     }
1489                 }
1490             }
1491         }
1492         return false;
1493     }
1494 
canProjectVideo(IMediaProjection projection)1495     private boolean canProjectVideo(IMediaProjection projection) {
1496         if (projection != null) {
1497             try {
1498                 if (projection.canProjectVideo()) {
1499                     return true;
1500                 }
1501             } catch (RemoteException e) {
1502                 Slog.e(TAG, "Unable to query projection service for permissions", e);
1503             }
1504         }
1505         if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
1506             return true;
1507         }
1508         return canProjectSecureVideo(projection);
1509     }
1510 
canProjectSecureVideo(IMediaProjection projection)1511     private boolean canProjectSecureVideo(IMediaProjection projection) {
1512         if (projection != null) {
1513             try {
1514                 if (projection.canProjectSecureVideo()) {
1515                     return true;
1516                 }
1517             } catch (RemoteException e) {
1518                 Slog.e(TAG, "Unable to query projection service for permissions", e);
1519             }
1520         }
1521         return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
1522     }
1523 
checkCallingPermission(String permission, String func)1524     private boolean checkCallingPermission(String permission, String func) {
1525         if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1526             return true;
1527         }
1528         final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
1529                 + ", uid=" + Binder.getCallingUid() + " requires " + permission;
1530         Slog.w(TAG, msg);
1531         return false;
1532     }
1533 
createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName)1534     private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig,
1535             IVirtualDisplayCallback callback, IMediaProjection projection,
1536             IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName) {
1537         final int callingUid = Binder.getCallingUid();
1538         if (!validatePackageName(callingUid, packageName)) {
1539             throw new SecurityException("packageName must match the calling uid");
1540         }
1541         if (callback == null) {
1542             throw new IllegalArgumentException("appToken must not be null");
1543         }
1544         if (virtualDisplayConfig == null) {
1545             throw new IllegalArgumentException("virtualDisplayConfig must not be null");
1546         }
1547         final Surface surface = virtualDisplayConfig.getSurface();
1548         int flags = virtualDisplayConfig.getFlags();
1549         if (virtualDevice != null) {
1550             final VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
1551             try {
1552                 if (!vdm.isValidVirtualDeviceId(virtualDevice.getDeviceId())) {
1553                     throw new SecurityException("Invalid virtual device");
1554                 }
1555             } catch (RemoteException ex) {
1556                 throw new SecurityException("Unable to validate virtual device");
1557             }
1558             final VirtualDeviceManagerInternal localVdm =
1559                     getLocalService(VirtualDeviceManagerInternal.class);
1560             flags |= localVdm.getBaseVirtualDisplayFlags(virtualDevice);
1561         }
1562 
1563         if (surface != null && surface.isSingleBuffered()) {
1564             throw new IllegalArgumentException("Surface can't be single-buffered");
1565         }
1566 
1567         if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1568             flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1569 
1570             // Public displays can't be allowed to show content when locked.
1571             if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
1572                 throw new IllegalArgumentException(
1573                         "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
1574             }
1575         }
1576         if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1577             flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1578         }
1579         if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1580             flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
1581         }
1582         // Put the display in the virtual device's display group only if it's not a mirror display,
1583         // and if it doesn't need its own display group. So effectively, mirror displays go into the
1584         // default display group.
1585         if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) == 0
1586                 && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0
1587                 && virtualDevice != null) {
1588             flags |= VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP;
1589         }
1590 
1591         // Check if the host app is attempting to reuse the token or capture again on the same
1592         // MediaProjection instance. Don't start recording if so; MediaProjectionManagerService
1593         // decides how to respond based on the target SDK.
1594         boolean waitForPermissionConsent = false;
1595         final long firstToken = Binder.clearCallingIdentity();
1596         try {
1597             if (projection != null) {
1598                 if (!getProjectionService().isCurrentProjection(projection)) {
1599                     throw new SecurityException("Cannot create VirtualDisplay with "
1600                             + "non-current MediaProjection");
1601                 }
1602                 if (!projection.isValid()) {
1603                     // Just log; MediaProjectionManagerService throws an exception.
1604                     Slog.w(TAG, "Reusing token: create virtual display for app reusing token");
1605                     // If the exception wasn't thrown, we continue and re-show the permission dialog
1606                     getProjectionService().requestConsentForInvalidProjection(projection);
1607                     // Declare that mirroring shouldn't begin until user reviews the permission
1608                     // dialog.
1609                     waitForPermissionConsent = true;
1610                 }
1611                 flags = projection.applyVirtualDisplayFlags(flags);
1612             }
1613         } catch (RemoteException e) {
1614             throw new SecurityException("Unable to validate media projection or flags", e);
1615         } finally {
1616             Binder.restoreCallingIdentity(firstToken);
1617         }
1618 
1619         if (callingUid != Process.SYSTEM_UID
1620                 && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1621             // Only a valid media projection or a virtual device can create a mirror virtual
1622             // display.
1623             if (!canProjectVideo(projection)
1624                     && !isMirroringSupportedByVirtualDevice(virtualDevice)) {
1625                 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1626                         + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1627                         + "MediaProjection token in order to create a screen sharing virtual "
1628                         + "display. In order to create a virtual display that does not perform "
1629                         + "screen sharing (mirroring), please use the flag "
1630                         + "VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY.");
1631             }
1632         }
1633         if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1634             if (!canProjectSecureVideo(projection)) {
1635                 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1636                         + "or an appropriate MediaProjection token to create a "
1637                         + "secure virtual display.");
1638             }
1639         }
1640 
1641         if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
1642             if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
1643                 EventLog.writeEvent(0x534e4554, "162627132", callingUid,
1644                         "Attempt to create a trusted display without holding permission!");
1645                 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
1646                         + "create a trusted virtual display.");
1647             }
1648         }
1649 
1650         // Mirror virtual displays created by a virtual device are not allowed to show
1651         // presentations.
1652         if (virtualDevice != null && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0
1653                 && (flags & VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
1654             Slog.d(TAG, "Mirror displays created by a virtual device cannot show "
1655                     + "presentations, hence ignoring flag VIRTUAL_DISPLAY_FLAG_PRESENTATION.");
1656             flags &= ~VIRTUAL_DISPLAY_FLAG_PRESENTATION;
1657         }
1658 
1659         if (callingUid != Process.SYSTEM_UID
1660                 && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
1661             // The virtualDevice instance has been validated above using isValidVirtualDevice
1662             if (virtualDevice == null
1663                     && !checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
1664                 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
1665                         + "create a virtual display which is not in the default DisplayGroup.");
1666             }
1667         }
1668 
1669         if ((flags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) {
1670             if (callingUid != Process.SYSTEM_UID
1671                     && !checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY,
1672                     "createVirtualDisplay()")) {
1673                 throw new SecurityException(
1674                         "Requires ADD_ALWAYS_UNLOCKED_DISPLAY permission to "
1675                                 + "create an always unlocked virtual display.");
1676             }
1677         }
1678 
1679         if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
1680             flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
1681         }
1682 
1683         // Sometimes users can have sensitive information in system decoration windows. An app
1684         // could create a virtual display with system decorations support and read the user info
1685         // from the surface.
1686         // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1687         // to trusted virtual displays.
1688         final int trustedDisplayWithSysDecorFlag =
1689                 (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1690                         | VIRTUAL_DISPLAY_FLAG_TRUSTED);
1691         if ((flags & trustedDisplayWithSysDecorFlag)
1692                 == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1693                 && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
1694             throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
1695         }
1696 
1697         final long secondToken = Binder.clearCallingIdentity();
1698         try {
1699             final int displayId;
1700             final String displayUniqueId = VirtualDisplayAdapter.generateDisplayUniqueId(
1701                     packageName, callingUid, virtualDisplayConfig);
1702 
1703             if (virtualDisplayConfig.isHomeSupported()) {
1704                 if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
1705                     Slog.w(TAG, "Display created with home support but lacks "
1706                             + "VIRTUAL_DISPLAY_FLAG_TRUSTED, ignoring the home support request.");
1707                 } else if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1708                     Slog.w(TAG, "Display created with home support but has "
1709                             + "VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, ignoring the home support "
1710                             + "request.");
1711                 } else {
1712                     mWindowManagerInternal.setHomeSupportedOnDisplay(displayUniqueId,
1713                             Display.TYPE_VIRTUAL, true);
1714                 }
1715             }
1716 
1717             synchronized (mSyncRoot) {
1718                 displayId =
1719                         createVirtualDisplayLocked(
1720                                 callback,
1721                                 projection,
1722                                 callingUid,
1723                                 packageName,
1724                                 displayUniqueId,
1725                                 virtualDevice,
1726                                 surface,
1727                                 flags,
1728                                 virtualDisplayConfig);
1729                 if (displayId != Display.INVALID_DISPLAY && virtualDevice != null && dwpc != null) {
1730                     mDisplayWindowPolicyControllers.put(
1731                             displayId, Pair.create(virtualDevice, dwpc));
1732                     Slog.d(TAG, "Virtual Display: successfully created virtual display");
1733                 }
1734             }
1735 
1736             if (displayId == Display.INVALID_DISPLAY && virtualDisplayConfig.isHomeSupported()
1737                     && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
1738                 // Failed to create the virtual display, so we should clean up the WM settings
1739                 // because it won't receive the onDisplayRemoved callback.
1740                 mWindowManagerInternal.clearDisplaySettings(displayUniqueId, Display.TYPE_VIRTUAL);
1741             }
1742 
1743             // Build a session describing the MediaProjection instance, if there is one. A session
1744             // for a VirtualDisplay or physical display mirroring is handled in DisplayContent.
1745             ContentRecordingSession session = null;
1746             try {
1747                 if (projection != null) {
1748                     IBinder taskWindowContainerToken = projection.getLaunchCookie() == null ? null
1749                             : projection.getLaunchCookie().binder;
1750                     int taskId = projection.getTaskId();
1751                     if (taskWindowContainerToken == null) {
1752                         // Record a particular display.
1753                         session = ContentRecordingSession.createDisplaySession(
1754                                 virtualDisplayConfig.getDisplayIdToMirror());
1755                     } else {
1756                         // Record a single task indicated by the launch cookie.
1757                         session = ContentRecordingSession.createTaskSession(
1758                                 taskWindowContainerToken, taskId);
1759                     }
1760                 }
1761             } catch (RemoteException e) {
1762                 Slog.e(TAG, "Unable to retrieve the projection's launch cookie", e);
1763             }
1764 
1765             // Ensure session details are only set when mirroring (through VirtualDisplay flags or
1766             // MediaProjection).
1767             final boolean shouldMirror =
1768                     projection != null || (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0;
1769             // When calling WindowManagerService#setContentRecordingSession, WindowManagerService
1770             // attempts to acquire a lock before executing its main body. Due to this, we need
1771             // to be sure that it isn't called while the DisplayManagerService is also holding
1772             // a lock, to avoid a deadlock scenario.
1773             if (shouldMirror && displayId != Display.INVALID_DISPLAY && session != null) {
1774                 // Only attempt to set content recording session if there are details to set and a
1775                 // VirtualDisplay has been successfully constructed.
1776                 session.setVirtualDisplayId(displayId);
1777                 // Don't start mirroring until user re-grants consent.
1778                 session.setWaitingForConsent(waitForPermissionConsent);
1779 
1780                 // We set the content recording session here on the server side instead of using
1781                 // a second AIDL call in MediaProjection. By ensuring that a virtual display has
1782                 // been constructed before calling setContentRecordingSession, we avoid a race
1783                 // condition between the DisplayManagerService & WindowManagerService which could
1784                 // lead to the MediaProjection being pre-emptively torn down.
1785                 try {
1786                     if (!getProjectionService().setContentRecordingSession(session, projection)) {
1787                         // Unable to start mirroring, so release VirtualDisplay. Projection service
1788                         // handles stopping the projection.
1789                         Slog.w(TAG, "Content Recording: failed to start mirroring - "
1790                                 + "releasing virtual display " + displayId);
1791                         releaseVirtualDisplayInternal(callback.asBinder());
1792                         return Display.INVALID_DISPLAY;
1793                     } else if (projection != null) {
1794                         // Indicate that this projection has been used to record, and can't be used
1795                         // again.
1796                         Slog.d(TAG, "Content Recording: notifying MediaProjection of successful"
1797                                 + " VirtualDisplay creation.");
1798                         projection.notifyVirtualDisplayCreated(displayId);
1799                     }
1800                 } catch (RemoteException e) {
1801                     Slog.e(TAG, "Unable to tell MediaProjectionManagerService to set the "
1802                             + "content recording session", e);
1803                     return displayId;
1804                 }
1805                 Slog.d(TAG, "Virtual Display: successfully set up virtual display "
1806                         + displayId);
1807             }
1808             return displayId;
1809         } finally {
1810             Binder.restoreCallingIdentity(secondToken);
1811         }
1812     }
1813 
createVirtualDisplayLocked( IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String uniqueId, IVirtualDevice virtualDevice, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig)1814     private int createVirtualDisplayLocked(
1815             IVirtualDisplayCallback callback,
1816             IMediaProjection projection,
1817             int callingUid,
1818             String packageName,
1819             String uniqueId,
1820             IVirtualDevice virtualDevice,
1821             Surface surface,
1822             int flags,
1823             VirtualDisplayConfig virtualDisplayConfig) {
1824         if (mVirtualDisplayAdapter == null) {
1825             Slog.w(
1826                     TAG,
1827                     "Rejecting request to create private virtual display "
1828                             + "because the virtual display adapter is not available.");
1829             return -1;
1830         }
1831 
1832         Slog.d(TAG, "Virtual Display: creating DisplayDevice with VirtualDisplayAdapter");
1833         DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
1834                 callback, projection, callingUid, packageName, uniqueId, surface, flags,
1835                 virtualDisplayConfig);
1836         if (device == null) {
1837             Slog.w(TAG, "Virtual Display: VirtualDisplayAdapter failed to create DisplayDevice");
1838             return -1;
1839         }
1840 
1841         // If the display is to be added to a device display group, we need to make the
1842         // LogicalDisplayMapper aware of the link between the new display and its associated virtual
1843         // device before triggering DISPLAY_DEVICE_EVENT_ADDED.
1844         if ((flags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) {
1845             if (virtualDevice != null) {
1846                 try {
1847                     final int virtualDeviceId = virtualDevice.getDeviceId();
1848                     mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(
1849                             device, virtualDeviceId);
1850                 } catch (RemoteException e) {
1851                     e.rethrowFromSystemServer();
1852                 }
1853             } else {
1854                 Slog.i(
1855                         TAG,
1856                         "Display created with VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP set, but no"
1857                             + " virtual device. The display will not be added to a device display"
1858                             + " group.");
1859             }
1860         }
1861 
1862         // DisplayDevice events are handled manually for Virtual Displays.
1863         // TODO: multi-display Fix this so that generic add/remove events are not handled in a
1864         // different code path for virtual displays.  Currently this happens so that we can
1865         // return a valid display ID synchronously upon successful Virtual Display creation.
1866         // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
1867         // called on the DisplayThread (which we don't want to wait for?).
1868         // One option would be to actually wait here on the binder thread
1869         // to be notified when the virtual display is created (or failed).
1870         mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
1871 
1872         final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
1873         if (display != null) {
1874             return display.getDisplayIdLocked();
1875         }
1876 
1877         // Something weird happened and the logical display was not created.
1878         Slog.w(TAG, "Rejecting request to create virtual display "
1879                 + "because the logical display was not created.");
1880         mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
1881         mDisplayDeviceRepo.onDisplayDeviceEvent(device,
1882                 DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1883         return -1;
1884     }
1885 
isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice)1886     private static boolean isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice) {
1887         return Flags.interactiveScreenMirror() && virtualDevice != null;
1888     }
1889 
resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)1890     private void resizeVirtualDisplayInternal(IBinder appToken,
1891             int width, int height, int densityDpi) {
1892         synchronized (mSyncRoot) {
1893             if (mVirtualDisplayAdapter == null) {
1894                 return;
1895             }
1896 
1897             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
1898         }
1899     }
1900 
setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)1901     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
1902         synchronized (mSyncRoot) {
1903             if (mVirtualDisplayAdapter == null) {
1904                 return;
1905             }
1906 
1907             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
1908         }
1909     }
1910 
releaseVirtualDisplayInternal(IBinder appToken)1911     private void releaseVirtualDisplayInternal(IBinder appToken) {
1912         synchronized (mSyncRoot) {
1913             if (mVirtualDisplayAdapter == null) {
1914                 return;
1915             }
1916 
1917             DisplayDevice device =
1918                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
1919             Slog.d(TAG, "Virtual Display: Display Device released");
1920             if (device != null) {
1921                 // TODO: multi-display - handle virtual displays the same as other display adapters.
1922                 mDisplayDeviceRepo.onDisplayDeviceEvent(device,
1923                         DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1924             }
1925         }
1926     }
1927 
setVirtualDisplayStateInternal(IBinder appToken, boolean isOn)1928     private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) {
1929         synchronized (mSyncRoot) {
1930             if (mVirtualDisplayAdapter == null) {
1931                 return;
1932             }
1933 
1934             mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn);
1935         }
1936     }
1937 
registerDefaultDisplayAdapters()1938     private void registerDefaultDisplayAdapters() {
1939         // Register default display adapters.
1940         synchronized (mSyncRoot) {
1941             // main display adapter
1942             registerDisplayAdapterLocked(mInjector.getLocalDisplayAdapter(mSyncRoot, mContext,
1943                     mHandler, mDisplayDeviceRepo, mFlags,
1944                     mDisplayNotificationManager));
1945 
1946             // Standalone VR devices rely on a virtual display as their primary display for
1947             // 2D UI. We register virtual display adapter along side the main display adapter
1948             // here so that it is ready by the time the system sends the home Intent for
1949             // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
1950             // the virtual display inside VR before any VR-specific apps even run.
1951             mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
1952                     mHandler, mDisplayDeviceRepo, mFlags);
1953             if (mVirtualDisplayAdapter != null) {
1954                 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
1955             }
1956         }
1957     }
1958 
registerAdditionalDisplayAdapters()1959     private void registerAdditionalDisplayAdapters() {
1960         synchronized (mSyncRoot) {
1961             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
1962                 registerOverlayDisplayAdapterLocked();
1963                 registerWifiDisplayAdapterLocked();
1964             }
1965         }
1966     }
1967 
registerOverlayDisplayAdapterLocked()1968     private void registerOverlayDisplayAdapterLocked() {
1969         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
1970                 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler, mFlags));
1971     }
1972 
registerWifiDisplayAdapterLocked()1973     private void registerWifiDisplayAdapterLocked() {
1974         if (mContext.getResources().getBoolean(
1975                 com.android.internal.R.bool.config_enableWifiDisplay)
1976                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
1977             mWifiDisplayAdapter = new WifiDisplayAdapter(
1978                     mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,
1979                     mPersistentDataStore, mFlags);
1980             registerDisplayAdapterLocked(mWifiDisplayAdapter);
1981         }
1982     }
1983 
shouldRegisterNonEssentialDisplayAdaptersLocked()1984     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
1985         // In safe mode, we disable non-essential display adapters to give the user
1986         // an opportunity to fix broken settings or other problems that might affect
1987         // system stability.
1988         return !mSafeMode;
1989     }
1990 
registerDisplayAdapterLocked(DisplayAdapter adapter)1991     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
1992         mDisplayAdapters.add(adapter);
1993         adapter.registerLocked();
1994     }
1995 
1996     @GuardedBy("mSyncRoot")
handleLogicalDisplayDisconnectedLocked(LogicalDisplay display)1997     private void handleLogicalDisplayDisconnectedLocked(LogicalDisplay display) {
1998         if (!mFlags.isConnectedDisplayManagementEnabled()) {
1999             Slog.e(TAG, "DisplayDisconnected shouldn't be received when the flag is off");
2000             return;
2001         }
2002         releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED);
2003         mExternalDisplayPolicy.handleLogicalDisplayDisconnectedLocked(display);
2004     }
2005 
2006     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
setupLogicalDisplay(LogicalDisplay display)2007     private void setupLogicalDisplay(LogicalDisplay display) {
2008         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
2009         final int displayId = display.getDisplayIdLocked();
2010         final boolean isDefault = displayId == Display.DEFAULT_DISPLAY;
2011         configureColorModeLocked(display, device);
2012         if (!mAreUserDisabledHdrTypesAllowed) {
2013             display.setUserDisabledHdrTypes(mUserDisabledHdrTypes);
2014         }
2015         if (isDefault) {
2016             notifyDefaultDisplayDeviceUpdated(display);
2017             recordStableDisplayStatsIfNeededLocked(display);
2018             recordTopInsetLocked(display);
2019         }
2020         if (mUserPreferredMode != null) {
2021             device.setUserPreferredDisplayModeLocked(mUserPreferredMode);
2022         } else {
2023             configurePreferredDisplayModeLocked(display);
2024         }
2025 
2026         DisplayPowerControllerInterface dpc = addDisplayPowerControllerLocked(display);
2027         if (dpc != null) {
2028             final int leadDisplayId = display.getLeadDisplayIdLocked();
2029             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
2030 
2031             // Loop through all the displays and check if any should follow this one - it could be
2032             // that the follower display was added before the lead display.
2033             mLogicalDisplayMapper.forEachLocked(d -> {
2034                 if (d.getLeadDisplayIdLocked() == displayId) {
2035                     DisplayPowerControllerInterface followerDpc =
2036                             mDisplayPowerControllers.get(d.getDisplayIdLocked());
2037                     if (followerDpc != null) {
2038                         updateDisplayPowerControllerLeaderLocked(followerDpc, displayId);
2039                     }
2040                 }
2041             });
2042         }
2043 
2044         mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
2045 
2046         final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault;
2047         mDisplayBrightnesses.append(displayId,
2048                 new BrightnessPair(brightnessDefault, brightnessDefault));
2049 
2050         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
2051     }
2052 
updateLogicalDisplayState(LogicalDisplay display)2053     private void updateLogicalDisplayState(LogicalDisplay display) {
2054         Runnable work = updateDisplayStateLocked(display.getPrimaryDisplayDeviceLocked());
2055         if (work != null) {
2056             work.run();
2057         }
2058         scheduleTraversalLocked(false);
2059     }
2060 
2061     @SuppressLint("AndroidFrameworkRequiresPermission")
handleLogicalDisplayConnectedLocked(LogicalDisplay display)2062     private void handleLogicalDisplayConnectedLocked(LogicalDisplay display) {
2063         if (!mFlags.isConnectedDisplayManagementEnabled()) {
2064             Slog.e(TAG, "DisplayConnected shouldn't be received when the flag is off");
2065             return;
2066         }
2067 
2068         setupLogicalDisplay(display);
2069 
2070         if (ExternalDisplayPolicy.isExternalDisplayLocked(display)) {
2071             mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(display);
2072         } else {
2073             sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);
2074         }
2075 
2076         updateLogicalDisplayState(display);
2077     }
2078 
2079     @SuppressLint("AndroidFrameworkRequiresPermission")
handleLogicalDisplayAddedLocked(LogicalDisplay display)2080     private void handleLogicalDisplayAddedLocked(LogicalDisplay display) {
2081         final int displayId = display.getDisplayIdLocked();
2082         final boolean isDefault = displayId == Display.DEFAULT_DISPLAY;
2083         if (!mFlags.isConnectedDisplayManagementEnabled()) {
2084             setupLogicalDisplay(display);
2085         }
2086 
2087         // Wake up waitForDefaultDisplay.
2088         if (isDefault) {
2089             mSyncRoot.notifyAll();
2090         }
2091 
2092         sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
2093 
2094         updateLogicalDisplayState(display);
2095 
2096         mExternalDisplayPolicy.handleLogicalDisplayAddedLocked(display);
2097     }
2098 
handleLogicalDisplayChangedLocked(@onNull LogicalDisplay display)2099     private void handleLogicalDisplayChangedLocked(@NonNull LogicalDisplay display) {
2100         updateViewportPowerStateLocked(display);
2101 
2102         final int displayId = display.getDisplayIdLocked();
2103         if (displayId == Display.DEFAULT_DISPLAY) {
2104             recordTopInsetLocked(display);
2105         }
2106         // We don't bother invalidating the display info caches here because any changes to the
2107         // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
2108         // this point.
2109         sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
2110 
2111         applyDisplayChangedLocked(display);
2112     }
2113 
applyDisplayChangedLocked(@onNull LogicalDisplay display)2114     private void applyDisplayChangedLocked(@NonNull LogicalDisplay display) {
2115         final int displayId = display.getDisplayIdLocked();
2116         scheduleTraversalLocked(false);
2117         mPersistentDataStore.saveIfNeeded();
2118 
2119         DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
2120         if (dpc != null) {
2121             final int leadDisplayId = display.getLeadDisplayIdLocked();
2122             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
2123 
2124             HighBrightnessModeMetadata hbmMetadata =
2125                     mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
2126             if (hbmMetadata != null) {
2127                 dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
2128             }
2129         }
2130     }
2131 
updateDisplayPowerControllerLeaderLocked( @onNull DisplayPowerControllerInterface dpc, int leadDisplayId)2132     private void updateDisplayPowerControllerLeaderLocked(
2133             @NonNull DisplayPowerControllerInterface dpc, int leadDisplayId) {
2134         if (dpc.getLeadDisplayId() == leadDisplayId) {
2135             // Lead display hasn't changed, nothing to do.
2136             return;
2137         }
2138 
2139         // If it has changed, then we need to unregister from the previous leader if there was one.
2140         final int prevLeaderId = dpc.getLeadDisplayId();
2141         if (prevLeaderId != Layout.NO_LEAD_DISPLAY) {
2142             final DisplayPowerControllerInterface prevLeader =
2143                     mDisplayPowerControllers.get(prevLeaderId);
2144             if (prevLeader != null) {
2145                 prevLeader.removeDisplayBrightnessFollower(dpc);
2146             }
2147         }
2148 
2149         // And then, if it's following, register it with the new one.
2150         if (leadDisplayId != Layout.NO_LEAD_DISPLAY) {
2151             final DisplayPowerControllerInterface newLeader =
2152                     mDisplayPowerControllers.get(leadDisplayId);
2153             if (newLeader != null) {
2154                 newLeader.addDisplayBrightnessFollower(dpc);
2155             }
2156         }
2157     }
2158 
handleLogicalDisplayFrameRateOverridesChangedLocked( @onNull LogicalDisplay display)2159     private void handleLogicalDisplayFrameRateOverridesChangedLocked(
2160             @NonNull LogicalDisplay display) {
2161         final int displayId = display.getDisplayIdLocked();
2162         // We don't bother invalidating the display info caches here because any changes to the
2163         // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
2164         // this point.
2165         sendDisplayEventFrameRateOverrideLocked(displayId);
2166         scheduleTraversalLocked(false);
2167     }
2168 
handleLogicalDisplayRemovedLocked(@onNull LogicalDisplay display)2169     private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
2170         // With display management, the display is removed when disabled, and it might still exist.
2171         // Resources must only be released when the disconnected signal is received.
2172         if (mFlags.isConnectedDisplayManagementEnabled()) {
2173             if (display.isValidLocked()) {
2174                 updateViewportPowerStateLocked(display);
2175             }
2176 
2177             // Note: This method is only called if the display was enabled before being removed.
2178             sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
2179 
2180             if (display.isValidLocked()) {
2181                 applyDisplayChangedLocked(display);
2182             }
2183             return;
2184         }
2185 
2186         releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
2187     }
2188 
releaseDisplayAndEmitEvent(LogicalDisplay display, int event)2189     private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
2190         final int displayId = display.getDisplayIdLocked();
2191 
2192         final DisplayPowerControllerInterface dpc =
2193                 mDisplayPowerControllers.removeReturnOld(displayId);
2194         if (dpc != null) {
2195             updateDisplayPowerControllerLeaderLocked(dpc, Layout.NO_LEAD_DISPLAY);
2196             dpc.stop();
2197         }
2198         mDisplayStates.delete(displayId);
2199         mDisplayBrightnesses.delete(displayId);
2200         DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
2201 
2202         if (mDisplayWindowPolicyControllers.contains(displayId)) {
2203             final IVirtualDevice virtualDevice =
2204                     mDisplayWindowPolicyControllers.removeReturnOld(displayId).first;
2205             if (virtualDevice != null) {
2206                 mHandler.post(() -> {
2207                     getLocalService(VirtualDeviceManagerInternal.class)
2208                             .onVirtualDisplayRemoved(virtualDevice, displayId);
2209                 });
2210             }
2211         }
2212 
2213         sendDisplayEventLocked(display, event);
2214         scheduleTraversalLocked(false);
2215     }
2216 
handleLogicalDisplaySwappedLocked(@onNull LogicalDisplay display)2217     private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) {
2218         handleLogicalDisplayChangedLocked(display);
2219 
2220         final int displayId = display.getDisplayIdLocked();
2221         if (displayId == Display.DEFAULT_DISPLAY) {
2222             notifyDefaultDisplayDeviceUpdated(display);
2223         }
2224         mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
2225     }
2226 
handleLogicalDisplayHdrSdrRatioChangedLocked(@onNull LogicalDisplay display)2227     private void handleLogicalDisplayHdrSdrRatioChangedLocked(@NonNull LogicalDisplay display) {
2228         sendDisplayEventIfEnabledLocked(display,
2229                 DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED);
2230     }
2231 
notifyDefaultDisplayDeviceUpdated(LogicalDisplay display)2232     private void notifyDefaultDisplayDeviceUpdated(LogicalDisplay display) {
2233         mDisplayModeDirector.defaultDisplayDeviceUpdated(display.getPrimaryDisplayDeviceLocked()
2234                 .mDisplayDeviceConfig);
2235     }
2236 
handleLogicalDisplayDeviceStateTransitionLocked(@onNull LogicalDisplay display)2237     private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
2238         final int displayId = display.getDisplayIdLocked();
2239         final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
2240         if (dpc != null) {
2241             final int leadDisplayId = display.getLeadDisplayIdLocked();
2242             updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
2243 
2244             HighBrightnessModeMetadata hbmMetadata =
2245                     mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
2246             if (hbmMetadata != null) {
2247                 dpc.onDisplayChanged(hbmMetadata, leadDisplayId);
2248             }
2249         }
2250     }
2251 
updateDisplayStateLocked(DisplayDevice device)2252     private Runnable updateDisplayStateLocked(DisplayDevice device) {
2253         // Blank or unblank the display immediately to match the state requested
2254         // by the display power controller (if known).
2255         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
2256         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
2257             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
2258             if (display == null) {
2259                 return null;
2260             }
2261             final int displayId = display.getDisplayIdLocked();
2262             final int state = mDisplayStates.get(displayId);
2263 
2264             // Only send a request for display state if display state has already been initialized.
2265             if (state != Display.STATE_UNKNOWN) {
2266                 final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
2267                 return device.requestDisplayStateLocked(
2268                         state,
2269                         brightnessPair.brightness,
2270                         brightnessPair.sdrBrightness,
2271                         display.getDisplayOffloadSessionLocked());
2272             }
2273         }
2274         return null;
2275     }
2276 
configureColorModeLocked(LogicalDisplay display, DisplayDevice device)2277     private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
2278         if (display.getPrimaryDisplayDeviceLocked() == device) {
2279             int colorMode = mPersistentDataStore.getColorMode(device);
2280             if (colorMode == Display.COLOR_MODE_INVALID) {
2281                 if (display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) {
2282                     colorMode = mDefaultDisplayDefaultColorMode;
2283                 } else {
2284                     colorMode = Display.COLOR_MODE_DEFAULT;
2285                 }
2286             }
2287             display.setRequestedColorModeLocked(colorMode);
2288         }
2289     }
2290 
configurePreferredDisplayModeLocked(LogicalDisplay display)2291     private void configurePreferredDisplayModeLocked(LogicalDisplay display) {
2292         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
2293         final Point userPreferredResolution =
2294                 mPersistentDataStore.getUserPreferredResolution(device);
2295         final float refreshRate = mPersistentDataStore.getUserPreferredRefreshRate(device);
2296         if (userPreferredResolution == null && Float.isNaN(refreshRate)) {
2297             return;
2298         }
2299         Display.Mode.Builder modeBuilder = new Display.Mode.Builder();
2300         if (userPreferredResolution != null) {
2301             modeBuilder.setResolution(userPreferredResolution.x, userPreferredResolution.y);
2302         }
2303         if (!Float.isNaN(refreshRate)) {
2304             modeBuilder.setRefreshRate(refreshRate);
2305         }
2306         device.setUserPreferredDisplayModeLocked(modeBuilder.build());
2307     }
2308 
2309     @GuardedBy("mSyncRoot")
storeHdrConversionModeLocked(HdrConversionMode hdrConversionMode)2310     private void storeHdrConversionModeLocked(HdrConversionMode hdrConversionMode) {
2311         Settings.Global.putInt(mContext.getContentResolver(),
2312                 Settings.Global.HDR_CONVERSION_MODE, hdrConversionMode.getConversionMode());
2313         final int preferredHdrOutputType =
2314                 hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_FORCE
2315                         ? hdrConversionMode.getPreferredHdrOutputType()
2316                         : Display.HdrCapabilities.HDR_TYPE_INVALID;
2317         Settings.Global.putInt(mContext.getContentResolver(),
2318                 Settings.Global.HDR_FORCE_CONVERSION_TYPE, preferredHdrOutputType);
2319     }
2320 
2321     @GuardedBy("mSyncRoot")
updateHdrConversionModeSettingsLocked()2322     void updateHdrConversionModeSettingsLocked() {
2323         final int conversionMode = Settings.Global.getInt(mContext.getContentResolver(),
2324                 Settings.Global.HDR_CONVERSION_MODE, mDefaultHdrConversionMode);
2325         final int preferredHdrOutputType = conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE
2326                 ? Settings.Global.getInt(mContext.getContentResolver(),
2327                 Settings.Global.HDR_FORCE_CONVERSION_TYPE,
2328                         Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)
2329                 : Display.HdrCapabilities.HDR_TYPE_INVALID;
2330         mHdrConversionMode = new HdrConversionMode(conversionMode, preferredHdrOutputType);
2331         setHdrConversionModeInternal(mHdrConversionMode);
2332     }
2333 
2334     // If we've never recorded stable device stats for this device before and they aren't
2335     // explicitly configured, go ahead and record the stable device stats now based on the status
2336     // of the default display at first boot.
recordStableDisplayStatsIfNeededLocked(LogicalDisplay d)2337     private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
2338         if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
2339             DisplayInfo info = d.getDisplayInfoLocked();
2340             setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
2341         }
2342     }
2343 
recordTopInsetLocked(@ullable LogicalDisplay d)2344     private void recordTopInsetLocked(@Nullable LogicalDisplay d) {
2345         // We must only persist the inset after boot has completed, otherwise we will end up
2346         // overwriting the persisted value before the masking flag has been loaded from the
2347         // resource overlay.
2348         if (!mSystemReady || d == null) {
2349             return;
2350         }
2351         int topInset = d.getInsets().top;
2352         if (topInset == mDefaultDisplayTopInset) {
2353             return;
2354         }
2355         mDefaultDisplayTopInset = topInset;
2356         SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));
2357     }
2358 
setStableDisplaySizeLocked(int width, int height)2359     private void setStableDisplaySizeLocked(int width, int height) {
2360         mStableDisplaySize = new Point(width, height);
2361         try {
2362             mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
2363         } finally {
2364             mPersistentDataStore.saveIfNeeded();
2365         }
2366     }
2367 
2368     @VisibleForTesting
getMinimumBrightnessCurveInternal()2369     Curve getMinimumBrightnessCurveInternal() {
2370         return mMinimumBrightnessCurve;
2371     }
2372 
getPreferredWideGamutColorSpaceIdInternal()2373     int getPreferredWideGamutColorSpaceIdInternal() {
2374         return mWideColorSpace.getId();
2375     }
2376 
getOverlaySupportInternal()2377     OverlayProperties getOverlaySupportInternal() {
2378         return mOverlayProperties;
2379     }
2380 
setUserPreferredDisplayModeInternal(int displayId, Display.Mode mode)2381     void setUserPreferredDisplayModeInternal(int displayId, Display.Mode mode) {
2382         synchronized (mSyncRoot) {
2383             if (mode != null && !isResolutionAndRefreshRateValid(mode)
2384                     && displayId == Display.INVALID_DISPLAY) {
2385                 throw new IllegalArgumentException("width, height and refresh rate of mode should "
2386                         + "be greater than 0 when setting the global user preferred display mode.");
2387             }
2388 
2389             final int resolutionHeight = mode == null ? Display.INVALID_DISPLAY_HEIGHT
2390                     : mode.getPhysicalHeight();
2391             final int resolutionWidth = mode == null ? Display.INVALID_DISPLAY_WIDTH
2392                     : mode.getPhysicalWidth();
2393             final float refreshRate = mode == null ? Display.INVALID_DISPLAY_REFRESH_RATE
2394                     : mode.getRefreshRate();
2395 
2396             storeModeInPersistentDataStoreLocked(
2397                     displayId, resolutionWidth, resolutionHeight, refreshRate);
2398             if (displayId != Display.INVALID_DISPLAY) {
2399                 setUserPreferredModeForDisplayLocked(displayId, mode);
2400             } else {
2401                 mUserPreferredMode = mode;
2402                 storeModeInGlobalSettingsLocked(
2403                         resolutionWidth, resolutionHeight, refreshRate, mode);
2404             }
2405         }
2406     }
2407 
storeModeInPersistentDataStoreLocked(int displayId, int resolutionWidth, int resolutionHeight, float refreshRate)2408     private void storeModeInPersistentDataStoreLocked(int displayId, int resolutionWidth,
2409             int resolutionHeight, float refreshRate) {
2410         DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId);
2411         if (displayDevice == null) {
2412             return;
2413         }
2414         try {
2415             mPersistentDataStore.setUserPreferredResolution(
2416                     displayDevice, resolutionWidth, resolutionHeight);
2417             mPersistentDataStore.setUserPreferredRefreshRate(displayDevice, refreshRate);
2418         } finally {
2419             mPersistentDataStore.saveIfNeeded();
2420         }
2421     }
2422 
setUserPreferredModeForDisplayLocked(int displayId, Display.Mode mode)2423     private void setUserPreferredModeForDisplayLocked(int displayId, Display.Mode mode) {
2424         DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId);
2425         if (displayDevice == null) {
2426             return;
2427         }
2428 
2429         // We do not yet support backup and restore for our PersistentDataStore, however, we want to
2430         // preserve the user's choice for HIGH/FULL resolution setting, so we when we are given a
2431         // a new resolution for the default display (normally stored in PDS), we will also save it
2432         // to a setting that is backed up.
2433         // TODO(b/330943343) - Consider a full fidelity DisplayBackupHelper for this instead.
2434         if (mFlags.isResolutionBackupRestoreEnabled() && displayId == Display.DEFAULT_DISPLAY) {
2435             // Checks to see which of the two resolutions is selected
2436             // TODO(b/330906790) Uses the same logic as Settings, but should be made to support
2437             //     more than two resolutions using explicit mode enums long-term.
2438             Point[] resolutions = displayDevice.getSupportedResolutionsLocked();
2439             if (resolutions.length == 2) {
2440                 Point newMode = new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight());
2441                 int resolutionMode = newMode.equals(resolutions[0]) ? RESOLUTION_MODE_HIGH
2442                         : newMode.equals(resolutions[1]) ? RESOLUTION_MODE_FULL
2443                         : RESOLUTION_MODE_UNKNOWN;
2444                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
2445                         Settings.Secure.SCREEN_RESOLUTION_MODE, resolutionMode,
2446                         UserHandle.USER_CURRENT);
2447             }
2448         }
2449 
2450         displayDevice.setUserPreferredDisplayModeLocked(mode);
2451     }
2452 
storeModeInGlobalSettingsLocked( int resolutionWidth, int resolutionHeight, float refreshRate, Display.Mode mode)2453     private void storeModeInGlobalSettingsLocked(
2454             int resolutionWidth, int resolutionHeight, float refreshRate, Display.Mode mode) {
2455         Settings.Global.putFloat(mContext.getContentResolver(),
2456                 Settings.Global.USER_PREFERRED_REFRESH_RATE, refreshRate);
2457         Settings.Global.putInt(mContext.getContentResolver(),
2458                 Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, resolutionHeight);
2459         Settings.Global.putInt(mContext.getContentResolver(),
2460                 Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth);
2461         mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
2462             device.setUserPreferredDisplayModeLocked(mode);
2463         });
2464     }
2465 
2466     @GuardedBy("mSyncRoot")
getEnabledAutoHdrTypesLocked()2467     private int[] getEnabledAutoHdrTypesLocked() {
2468         IntArray autoHdrOutputTypesArray = new IntArray();
2469         for (int type : getSupportedHdrOutputTypesInternal()) {
2470             boolean isDisabled = false;
2471             for (int disabledType : mUserDisabledHdrTypes) {
2472                 if (type == disabledType) {
2473                     isDisabled = true;
2474                     break;
2475                 }
2476             }
2477             if (!isDisabled) {
2478                 autoHdrOutputTypesArray.add(type);
2479             }
2480         }
2481         return autoHdrOutputTypesArray.toArray();
2482     }
2483 
2484     @GuardedBy("mSyncRoot")
hdrConversionIntroducesLatencyLocked()2485     private boolean hdrConversionIntroducesLatencyLocked() {
2486         HdrConversionMode mode = getHdrConversionModeSettingInternal();
2487         final int preferredHdrOutputType =
2488                 mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM
2489                         ? mSystemPreferredHdrOutputType : mode.getPreferredHdrOutputType();
2490         if (preferredHdrOutputType != Display.HdrCapabilities.HDR_TYPE_INVALID) {
2491             int[] hdrTypesWithLatency = mInjector.getHdrOutputTypesWithLatency();
2492             return ArrayUtils.contains(hdrTypesWithLatency, preferredHdrOutputType);
2493         }
2494         return false;
2495     }
2496 
getUserPreferredDisplayModeInternal(int displayId)2497     Display.Mode getUserPreferredDisplayModeInternal(int displayId) {
2498         synchronized (mSyncRoot) {
2499             if (displayId == Display.INVALID_DISPLAY) {
2500                 return mUserPreferredMode;
2501             }
2502             DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId);
2503             if (displayDevice == null) {
2504                 return null;
2505             }
2506             return displayDevice.getUserPreferredDisplayModeLocked();
2507         }
2508     }
2509 
getSystemPreferredDisplayModeInternal(int displayId)2510     Display.Mode getSystemPreferredDisplayModeInternal(int displayId) {
2511         synchronized (mSyncRoot) {
2512             final DisplayDevice device = getDeviceForDisplayLocked(displayId);
2513             if (device == null) {
2514                 return null;
2515             }
2516             return device.getSystemPreferredDisplayModeLocked();
2517         }
2518     }
2519 
setHdrConversionModeInternal(HdrConversionMode hdrConversionMode)2520     void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
2521         if (!mInjector.getHdrOutputConversionSupport()) {
2522             return;
2523         }
2524         int[] autoHdrOutputTypes = null;
2525         synchronized (mSyncRoot) {
2526             if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM
2527                     && hdrConversionMode.getPreferredHdrOutputType()
2528                     != Display.HdrCapabilities.HDR_TYPE_INVALID) {
2529                 throw new IllegalArgumentException("preferredHdrOutputType must not be set if"
2530                         + " the conversion mode is HDR_CONVERSION_SYSTEM");
2531             }
2532             mHdrConversionMode = hdrConversionMode;
2533             storeHdrConversionModeLocked(mHdrConversionMode);
2534 
2535             // For auto mode, all supported HDR types are allowed except the ones specifically
2536             // disabled by the user.
2537             if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) {
2538                 autoHdrOutputTypes = getEnabledAutoHdrTypesLocked();
2539             }
2540 
2541             int conversionMode = hdrConversionMode.getConversionMode();
2542             int preferredHdrType = hdrConversionMode.getPreferredHdrOutputType();
2543             // If the HDR conversion is disabled by an app through WindowManager.LayoutParams, then
2544             // set HDR conversion mode to HDR_CONVERSION_PASSTHROUGH.
2545             if (mOverrideHdrConversionMode == null) {
2546                 // HDR_CONVERSION_FORCE with HDR_TYPE_INVALID is used to represent forcing SDR type.
2547                 // But, internally SDR is selected by using passthrough mode.
2548                 if (conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE
2549                         && preferredHdrType == Display.HdrCapabilities.HDR_TYPE_INVALID) {
2550                     conversionMode = HdrConversionMode.HDR_CONVERSION_PASSTHROUGH;
2551                 }
2552             } else {
2553                 conversionMode = mOverrideHdrConversionMode.getConversionMode();
2554                 preferredHdrType = mOverrideHdrConversionMode.getPreferredHdrOutputType();
2555                 autoHdrOutputTypes = null;
2556             }
2557             mSystemPreferredHdrOutputType = mInjector.setHdrConversionMode(
2558                     conversionMode, preferredHdrType, autoHdrOutputTypes);
2559         }
2560     }
2561 
getHdrConversionModeSettingInternal()2562     HdrConversionMode getHdrConversionModeSettingInternal() {
2563         if (!mInjector.getHdrOutputConversionSupport()) {
2564             return HDR_CONVERSION_MODE_UNSUPPORTED;
2565         }
2566         synchronized (mSyncRoot) {
2567             if (mHdrConversionMode != null) {
2568                 return mHdrConversionMode;
2569             }
2570         }
2571         return new HdrConversionMode(mDefaultHdrConversionMode);
2572     }
2573 
getHdrConversionModeInternal()2574     HdrConversionMode getHdrConversionModeInternal() {
2575         if (!mInjector.getHdrOutputConversionSupport()) {
2576             return HDR_CONVERSION_MODE_UNSUPPORTED;
2577         }
2578         HdrConversionMode mode;
2579         synchronized (mSyncRoot) {
2580             mode = mOverrideHdrConversionMode != null
2581                     ? mOverrideHdrConversionMode
2582                     : mHdrConversionMode;
2583             // Handle default: PASSTHROUGH. Don't include the system-preferred type.
2584             if (mode == null
2585                     && mDefaultHdrConversionMode == HdrConversionMode.HDR_CONVERSION_PASSTHROUGH) {
2586                 return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH);
2587             }
2588             // Handle default or current mode: SYSTEM. Include the system preferred type.
2589             // mOverrideHdrConversionMode and mHdrConversionMode do not include the system
2590             // preferred type, it is kept separately in mSystemPreferredHdrOutputType.
2591             if (mode == null
2592                     || mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) {
2593                 return new HdrConversionMode(
2594                         HdrConversionMode.HDR_CONVERSION_SYSTEM, mSystemPreferredHdrOutputType);
2595             }
2596         }
2597         return mode;
2598     }
2599 
getSupportedHdrOutputTypesInternal()2600     private @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypesInternal() {
2601         if (mSupportedHdrOutputType == null) {
2602             mSupportedHdrOutputType = mInjector.getSupportedHdrOutputTypes();
2603         }
2604         return mSupportedHdrOutputType;
2605     }
2606 
setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled)2607     void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
2608         mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
2609     }
2610 
shouldAlwaysRespectAppRequestedModeInternal()2611     boolean shouldAlwaysRespectAppRequestedModeInternal() {
2612         return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode();
2613     }
2614 
setRefreshRateSwitchingTypeInternal(@isplayManager.SwitchingType int newValue)2615     void setRefreshRateSwitchingTypeInternal(@DisplayManager.SwitchingType int newValue) {
2616         mDisplayModeDirector.setModeSwitchingType(newValue);
2617     }
2618 
2619     @DisplayManager.SwitchingType
getRefreshRateSwitchingTypeInternal()2620     int getRefreshRateSwitchingTypeInternal() {
2621         return mDisplayModeDirector.getModeSwitchingType();
2622     }
2623 
getDisplayDecorationSupportInternal(int displayId)2624     private DisplayDecorationSupport getDisplayDecorationSupportInternal(int displayId) {
2625         final IBinder displayToken = getDisplayToken(displayId);
2626         if (null == displayToken) {
2627             return null;
2628         }
2629         return SurfaceControl.getDisplayDecorationSupport(displayToken);
2630     }
2631 
setBrightnessConfigurationForDisplayInternal( @ullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId, String packageName)2632     private void setBrightnessConfigurationForDisplayInternal(
2633             @Nullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId,
2634             String packageName) {
2635         validateBrightnessConfiguration(c);
2636         final int userSerial = getUserManager().getUserSerialNumber(userId);
2637         synchronized (mSyncRoot) {
2638             try {
2639                 DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
2640                 if (displayDevice == null) {
2641                     return;
2642                 }
2643                 if (mLogicalDisplayMapper.getDisplayLocked(displayDevice) != null
2644                         && mLogicalDisplayMapper.getDisplayLocked(displayDevice)
2645                         .getDisplayInfoLocked().type == Display.TYPE_INTERNAL && c != null) {
2646                     FrameworkStatsLog.write(FrameworkStatsLog.BRIGHTNESS_CONFIGURATION_UPDATED,
2647                                 c.getCurve().first,
2648                                 c.getCurve().second,
2649                                 // should not be logged for virtual displays
2650                                 uniqueId);
2651                 }
2652                 mPersistentDataStore.setBrightnessConfigurationForDisplayLocked(c, displayDevice,
2653                         userSerial, packageName);
2654             } finally {
2655                 mPersistentDataStore.saveIfNeeded();
2656             }
2657             if (userId != mCurrentUserId) {
2658                 return;
2659             }
2660             DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
2661             if (dpc != null) {
2662                 dpc.setBrightnessConfiguration(c, /* shouldResetShortTermModel= */ true);
2663             }
2664         }
2665     }
2666 
getDpcFromUniqueIdLocked(String uniqueId)2667     private DisplayPowerControllerInterface getDpcFromUniqueIdLocked(String uniqueId) {
2668         final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
2669         final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice);
2670         if (logicalDisplay != null) {
2671             final int displayId = logicalDisplay.getDisplayIdLocked();
2672             return mDisplayPowerControllers.get(displayId);
2673         }
2674         return null;
2675     }
2676 
2677     @VisibleForTesting
validateBrightnessConfiguration(BrightnessConfiguration config)2678     void validateBrightnessConfiguration(BrightnessConfiguration config) {
2679         if (config == null) {
2680             return;
2681         }
2682         if (isBrightnessConfigurationTooDark(config)) {
2683             throw new IllegalArgumentException("brightness curve is too dark");
2684         }
2685     }
2686 
isBrightnessConfigurationTooDark(BrightnessConfiguration config)2687     private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
2688         Pair<float[], float[]> curve = config.getCurve();
2689         float[] lux = curve.first;
2690         float[] nits = curve.second;
2691         for (int i = 0; i < lux.length; i++) {
2692             if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
2693                 return true;
2694             }
2695         }
2696         return false;
2697     }
2698 
loadBrightnessConfigurations()2699     private void loadBrightnessConfigurations() {
2700         int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
2701         synchronized (mSyncRoot) {
2702             mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> {
2703                 final String uniqueId =
2704                         logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
2705                 final BrightnessConfiguration config =
2706                         getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial);
2707                 if (config != null) {
2708                     final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
2709                             logicalDisplay.getDisplayIdLocked());
2710                     if (dpc != null) {
2711                         dpc.setBrightnessConfiguration(config,
2712                                 /* shouldResetShortTermModel= */ false);
2713                     }
2714                 }
2715             });
2716         }
2717     }
2718 
performTraversalLocked(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)2719     private void performTraversalLocked(SurfaceControl.Transaction t,
2720             SparseArray<SurfaceControl.Transaction> displayTransactions) {
2721         // Clear all viewports before configuring displays so that we can keep
2722         // track of which ones we have configured.
2723         clearViewportsLocked();
2724 
2725         // Configure each display device.
2726         mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> {
2727             final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
2728             final SurfaceControl.Transaction displayTransaction =
2729                     displayTransactions.get(display.getDisplayIdLocked(), t);
2730             if (device != null) {
2731                 configureDisplayLocked(displayTransaction, device);
2732                 device.performTraversalLocked(displayTransaction);
2733             }
2734         });
2735 
2736         // Tell the input system about these new viewports.
2737         if (mInputManagerInternal != null) {
2738             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
2739         }
2740     }
2741 
setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate, float requestedMaxRefreshRate, boolean preferMinimalPostProcessing, boolean disableHdrConversion, boolean inTraversal)2742     void setDisplayPropertiesInternal(int displayId, boolean hasContent,
2743             float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate,
2744             float requestedMaxRefreshRate, boolean preferMinimalPostProcessing,
2745             boolean disableHdrConversion, boolean inTraversal) {
2746         synchronized (mSyncRoot) {
2747             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2748             if (display == null) {
2749                 return;
2750             }
2751 
2752             boolean shouldScheduleTraversal = false;
2753 
2754             if (display.hasContentLocked() != hasContent) {
2755                 if (DEBUG) {
2756                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
2757                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
2758                 }
2759 
2760                 display.setHasContentLocked(hasContent);
2761                 shouldScheduleTraversal = true;
2762             }
2763 
2764             mDisplayModeDirector.getAppRequestObserver().setAppRequest(displayId, requestedModeId,
2765                     requestedRefreshRate, requestedMinRefreshRate, requestedMaxRefreshRate);
2766 
2767             // TODO(b/202378408) set minimal post-processing only if it's supported once we have a
2768             // separate API for disabling on-device processing.
2769             boolean mppRequest = isMinimalPostProcessingAllowed() && preferMinimalPostProcessing;
2770             // If HDR conversion introduces latency, disable that in case minimal
2771             // post-processing is requested
2772             boolean disableHdrConversionForLatency =
2773                     mppRequest && hdrConversionIntroducesLatencyLocked();
2774 
2775             if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) {
2776                 display.setRequestedMinimalPostProcessingLocked(mppRequest);
2777                 shouldScheduleTraversal = true;
2778             }
2779 
2780             if (shouldScheduleTraversal) {
2781                 scheduleTraversalLocked(inTraversal);
2782             }
2783 
2784             if (mHdrConversionMode == null) {
2785                 return;
2786             }
2787             // HDR conversion is disabled in two cases:
2788             // - HDR conversion introduces latency and minimal post-processing is requested
2789             // - app requests to disable HDR conversion
2790             if (mOverrideHdrConversionMode == null && (disableHdrConversion
2791                     || disableHdrConversionForLatency)) {
2792                 mOverrideHdrConversionMode =
2793                             new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH);
2794                 setHdrConversionModeInternal(mHdrConversionMode);
2795                 handleLogicalDisplayChangedLocked(display);
2796             } else if (mOverrideHdrConversionMode != null && !disableHdrConversion
2797                     && !disableHdrConversionForLatency) {
2798                 mOverrideHdrConversionMode = null;
2799                 setHdrConversionModeInternal(mHdrConversionMode);
2800                 handleLogicalDisplayChangedLocked(display);
2801             }
2802         }
2803     }
2804 
setDisplayOffsetsInternal(int displayId, int x, int y)2805     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
2806         synchronized (mSyncRoot) {
2807             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2808             if (display == null) {
2809                 return;
2810             }
2811             if (display.getDisplayOffsetXLocked() != x
2812                     || display.getDisplayOffsetYLocked() != y) {
2813                 if (DEBUG) {
2814                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
2815                             + x + ", " + y + ")");
2816                 }
2817                 display.setDisplayOffsetsLocked(x, y);
2818                 scheduleTraversalLocked(false);
2819             }
2820         }
2821     }
2822 
setDisplayScalingDisabledInternal(int displayId, boolean disable)2823     private void setDisplayScalingDisabledInternal(int displayId, boolean disable) {
2824         synchronized (mSyncRoot) {
2825             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2826             if (display == null) {
2827                 return;
2828             }
2829             if (display.isDisplayScalingDisabled() != disable) {
2830                 if (DEBUG) {
2831                     Slog.d(TAG, "Display " + displayId + " content scaling disabled = " + disable);
2832                 }
2833                 display.setDisplayScalingDisabledLocked(disable);
2834                 scheduleTraversalLocked(false);
2835             }
2836         }
2837     }
2838 
2839     // Updates the lists of UIDs that are present on displays.
setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs)2840     private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
2841         synchronized (mSyncRoot) {
2842             mDisplayAccessUIDs.clear();
2843             for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) {
2844                 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i),
2845                         newDisplayAccessUIDs.valueAt(i));
2846             }
2847         }
2848     }
2849 
2850     // Checks if provided UID's content is present on the display and UID has access to it.
isUidPresentOnDisplayInternal(int uid, int displayId)2851     private boolean isUidPresentOnDisplayInternal(int uid, int displayId) {
2852         synchronized (mSyncRoot) {
2853             final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId);
2854             return displayUIDs != null && displayUIDs.indexOf(uid) != -1;
2855         }
2856     }
2857 
2858     @Nullable
getDisplayToken(int displayId)2859     private IBinder getDisplayToken(int displayId) {
2860         synchronized (mSyncRoot) {
2861             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
2862             if (display != null) {
2863                 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
2864                 if (device != null) {
2865                     return device.getDisplayTokenLocked();
2866                 }
2867             }
2868         }
2869 
2870         return null;
2871     }
2872 
systemScreenshotInternal(int displayId)2873     private ScreenCapture.ScreenshotHardwareBuffer systemScreenshotInternal(int displayId) {
2874         final ScreenCapture.DisplayCaptureArgs captureArgs;
2875         synchronized (mSyncRoot) {
2876             final IBinder token = getDisplayToken(displayId);
2877             if (token == null) {
2878                 return null;
2879             }
2880             final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
2881             if (logicalDisplay == null) {
2882                 return null;
2883             }
2884 
2885             final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
2886             captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token)
2887                     .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
2888                     .setCaptureSecureLayers(true)
2889                     .setAllowProtected(true)
2890                     .build();
2891         }
2892         return ScreenCapture.captureDisplay(captureArgs);
2893     }
2894 
userScreenshotInternal(int displayId)2895     private ScreenCapture.ScreenshotHardwareBuffer userScreenshotInternal(int displayId) {
2896         final ScreenCapture.DisplayCaptureArgs captureArgs;
2897         synchronized (mSyncRoot) {
2898             final IBinder token = getDisplayToken(displayId);
2899             if (token == null) {
2900                 return null;
2901             }
2902 
2903             captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token)
2904                             .build();
2905         }
2906         return ScreenCapture.captureDisplay(captureArgs);
2907     }
2908 
2909     @VisibleForTesting
getDisplayedContentSamplingAttributesInternal( int displayId)2910     DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal(
2911             int displayId) {
2912         final IBinder token = getDisplayToken(displayId);
2913         if (token == null) {
2914             return null;
2915         }
2916         return SurfaceControl.getDisplayedContentSamplingAttributes(token);
2917     }
2918 
2919     @VisibleForTesting
setDisplayedContentSamplingEnabledInternal( int displayId, boolean enable, int componentMask, int maxFrames)2920     boolean setDisplayedContentSamplingEnabledInternal(
2921             int displayId, boolean enable, int componentMask, int maxFrames) {
2922         final IBinder token = getDisplayToken(displayId);
2923         if (token == null) {
2924             return false;
2925         }
2926         return SurfaceControl.setDisplayedContentSamplingEnabled(
2927                 token, enable, componentMask, maxFrames);
2928     }
2929 
2930     @VisibleForTesting
getDisplayedContentSampleInternal(int displayId, long maxFrames, long timestamp)2931     DisplayedContentSample getDisplayedContentSampleInternal(int displayId,
2932             long maxFrames, long timestamp) {
2933         final IBinder token = getDisplayToken(displayId);
2934         if (token == null) {
2935             return null;
2936         }
2937         return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
2938     }
2939 
resetBrightnessConfigurations()2940     void resetBrightnessConfigurations() {
2941         mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(),
2942                 mContext.getPackageName());
2943         mLogicalDisplayMapper.forEachLocked((logicalDisplay -> {
2944             if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
2945                 return;
2946             }
2947             final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
2948             setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(),
2949                     mContext.getPackageName());
2950         }));
2951     }
2952 
setAutoBrightnessLoggingEnabled(boolean enabled)2953     void setAutoBrightnessLoggingEnabled(boolean enabled) {
2954         synchronized (mSyncRoot) {
2955             final DisplayPowerControllerInterface displayPowerController =
2956                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
2957             if (displayPowerController != null) {
2958                 displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
2959             }
2960         }
2961     }
2962 
setDisplayWhiteBalanceLoggingEnabled(boolean enabled)2963     void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
2964         synchronized (mSyncRoot) {
2965             final DisplayPowerControllerInterface displayPowerController =
2966                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
2967             if (displayPowerController != null) {
2968                 displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
2969             }
2970         }
2971     }
2972 
setDisplayModeDirectorLoggingEnabled(boolean enabled)2973     void setDisplayModeDirectorLoggingEnabled(boolean enabled) {
2974         synchronized (mSyncRoot) {
2975             mDisplayModeDirector.setLoggingEnabled(enabled);
2976         }
2977     }
2978 
getActiveDisplayModeAtStart(int displayId)2979     Display.Mode getActiveDisplayModeAtStart(int displayId) {
2980         synchronized (mSyncRoot) {
2981             final DisplayDevice device = getDeviceForDisplayLocked(displayId);
2982             if (device == null) {
2983                 return null;
2984             }
2985             return device.getActiveDisplayModeAtStartLocked();
2986         }
2987     }
2988 
setAmbientColorTemperatureOverride(float cct)2989     void setAmbientColorTemperatureOverride(float cct) {
2990         synchronized (mSyncRoot) {
2991             final DisplayPowerControllerInterface displayPowerController =
2992                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
2993             if (displayPowerController != null) {
2994                 displayPowerController.setAmbientColorTemperatureOverride(cct);
2995             }
2996         }
2997     }
2998 
setDockedAndIdleEnabled(boolean enabled, int displayId)2999     void setDockedAndIdleEnabled(boolean enabled, int displayId) {
3000         synchronized (mSyncRoot) {
3001             final DisplayPowerControllerInterface displayPowerController =
3002                     mDisplayPowerControllers.get(displayId);
3003             if (displayPowerController != null) {
3004                 displayPowerController.setAutomaticScreenBrightnessMode(enabled
3005                         ? AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE
3006                         : AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT);
3007             }
3008         }
3009     }
3010 
clearViewportsLocked()3011     private void clearViewportsLocked() {
3012         mViewports.clear();
3013     }
3014 
getViewportType(DisplayDeviceInfo info)3015     private Optional<Integer> getViewportType(DisplayDeviceInfo info) {
3016         // Get the corresponding viewport type.
3017         switch (info.touch) {
3018             case DisplayDeviceInfo.TOUCH_INTERNAL:
3019                 return Optional.of(VIEWPORT_INTERNAL);
3020             case DisplayDeviceInfo.TOUCH_EXTERNAL:
3021                 return Optional.of(VIEWPORT_EXTERNAL);
3022             case DisplayDeviceInfo.TOUCH_VIRTUAL:
3023                 if (!TextUtils.isEmpty(info.uniqueId)) {
3024                     return Optional.of(VIEWPORT_VIRTUAL);
3025                 }
3026                 // fallthrough
3027             default:
3028                 if (DEBUG) {
3029                     Slog.w(TAG, "Display " + info + " does not support input device matching.");
3030                 }
3031         }
3032         return Optional.empty();
3033     }
3034 
configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device)3035     private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
3036         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
3037 
3038         // Find the logical display that the display device is showing.
3039         // Certain displays only ever show their own content.
3040         LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
3041 
3042         // Apply the logical display configuration to the display device.
3043         if (display == null) {
3044             // TODO: no logical display for the device, blank it
3045             Slog.w(TAG, "Missing logical display to use for physical display device: "
3046                     + device.getDisplayDeviceInfoLocked());
3047             return;
3048         }
3049         display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
3050         final Optional<Integer> viewportType = getViewportType(info);
3051         if (viewportType.isPresent()) {
3052             populateViewportLocked(viewportType.get(), display.getDisplayIdLocked(), device, info);
3053         }
3054     }
3055 
3056     /**
3057      * Get internal or external viewport. Create it if does not currently exist.
3058      * @param viewportType - either INTERNAL or EXTERNAL
3059      * @return the viewport with the requested type
3060      */
getViewportLocked(int viewportType, String uniqueId)3061     private DisplayViewport getViewportLocked(int viewportType, String uniqueId) {
3062         if (viewportType != VIEWPORT_INTERNAL && viewportType != VIEWPORT_EXTERNAL
3063                 && viewportType != VIEWPORT_VIRTUAL) {
3064             Slog.wtf(TAG, "Cannot call getViewportByTypeLocked for type "
3065                     + DisplayViewport.typeToString(viewportType));
3066             return null;
3067         }
3068 
3069         DisplayViewport viewport;
3070         final int count = mViewports.size();
3071         for (int i = 0; i < count; i++) {
3072             viewport = mViewports.get(i);
3073             if (viewport.type == viewportType && uniqueId.equals(viewport.uniqueId)) {
3074                 return viewport;
3075             }
3076         }
3077 
3078         // Creates the viewport if none exists.
3079         viewport = new DisplayViewport();
3080         viewport.type = viewportType;
3081         viewport.uniqueId = uniqueId;
3082         mViewports.add(viewport);
3083         return viewport;
3084     }
3085 
populateViewportLocked(int viewportType, int displayId, DisplayDevice device, DisplayDeviceInfo info)3086     private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device,
3087             DisplayDeviceInfo info) {
3088         final DisplayViewport viewport = getViewportLocked(viewportType, info.uniqueId);
3089         device.populateViewportLocked(viewport);
3090         viewport.valid = true;
3091         viewport.displayId = displayId;
3092         viewport.isActive = Display.isActiveState(info.state);
3093     }
3094 
updateViewportPowerStateLocked(LogicalDisplay display)3095     private void updateViewportPowerStateLocked(LogicalDisplay display) {
3096         final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
3097         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
3098         final Optional<Integer> viewportType = getViewportType(info);
3099         if (viewportType.isPresent()) {
3100             for (DisplayViewport d : mViewports) {
3101                 if (d.type == viewportType.get() && info.uniqueId.equals(d.uniqueId)) {
3102                     // Update display view port power state
3103                     d.isActive = Display.isActiveState(info.state);
3104                 }
3105             }
3106             if (mInputManagerInternal != null) {
3107                 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
3108             }
3109         }
3110     }
3111 
3112     // Send a display event if the display is enabled
sendDisplayEventIfEnabledLocked(@onNull LogicalDisplay display, @DisplayEvent int event)3113     private void sendDisplayEventIfEnabledLocked(@NonNull LogicalDisplay display,
3114                                                  @DisplayEvent int event) {
3115         final boolean displayIsEnabled = display.isEnabledLocked();
3116         if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
3117             Trace.instant(Trace.TRACE_TAG_POWER,
3118                     "sendDisplayEventLocked#event=" + event + ",displayEnabled="
3119                             + displayIsEnabled);
3120         }
3121 
3122         // Only send updates outside of DisplayManagerService for enabled displays
3123         if (displayIsEnabled) {
3124             sendDisplayEventLocked(display, event);
3125         } else if (mExtraDisplayEventLogging) {
3126             Slog.i(TAG, "Not Sending Display Event; display is not enabled: " + display);
3127         }
3128     }
3129 
sendDisplayEventLocked(@onNull LogicalDisplay display, @DisplayEvent int event)3130     private void sendDisplayEventLocked(@NonNull LogicalDisplay display, @DisplayEvent int event) {
3131         int displayId = display.getDisplayIdLocked();
3132         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
3133         if (mExtraDisplayEventLogging) {
3134             Slog.i(TAG, "Deliver Display Event on Handler: " + event);
3135         }
3136         mHandler.sendMessage(msg);
3137     }
3138 
sendDisplayGroupEvent(int groupId, int event)3139     private void sendDisplayGroupEvent(int groupId, int event) {
3140         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event);
3141         mHandler.sendMessage(msg);
3142     }
3143 
sendDisplayEventFrameRateOverrideLocked(int displayId)3144     private void sendDisplayEventFrameRateOverrideLocked(int displayId) {
3145         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
3146                 displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
3147         mHandler.sendMessage(msg);
3148     }
3149 
3150     // Requests that performTraversals be called at a
3151     // later time to apply changes to surfaces and displays.
scheduleTraversalLocked(boolean inTraversal)3152     private void scheduleTraversalLocked(boolean inTraversal) {
3153         if (!mPendingTraversal && mWindowManagerInternal != null) {
3154             mPendingTraversal = true;
3155             if (!inTraversal) {
3156                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
3157             }
3158         }
3159     }
3160 
3161     // Check if the target app is in cached mode
isUidCached(int uid)3162     private boolean isUidCached(int uid) {
3163         if (mActivityManagerInternal == null || uid < FIRST_APPLICATION_UID) {
3164             return false;
3165         }
3166         int procState = mActivityManagerInternal.getUidProcessState(uid);
3167         int importance = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState);
3168         return importance >= IMPORTANCE_CACHED;
3169     }
3170 
3171     // Runs on Handler thread.
3172     // Delivers display event notifications to callbacks.
deliverDisplayEvent(int displayId, ArraySet<Integer> uids, @DisplayEvent int event)3173     private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids,
3174             @DisplayEvent int event) {
3175         if (DEBUG || mExtraDisplayEventLogging) {
3176             Slog.d(TAG, "Delivering display event: displayId="
3177                     + displayId + ", event=" + event
3178                     + (uids != null ? ", uids=" + uids : ""));
3179         }
3180         if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
3181             Trace.instant(Trace.TRACE_TAG_POWER,
3182                     "deliverDisplayEvent#event=" + event + ",displayId="
3183                             + displayId   + (uids != null ? ", uids=" + uids : ""));
3184         }
3185         // Grab the lock and copy the callbacks.
3186         final int count;
3187         synchronized (mSyncRoot) {
3188             count = mCallbacks.size();
3189             mTempCallbacks.clear();
3190             for (int i = 0; i < count; i++) {
3191                 if (uids == null || uids.contains(mCallbacks.valueAt(i).mUid)) {
3192                     mTempCallbacks.add(mCallbacks.valueAt(i));
3193                 }
3194             }
3195         }
3196 
3197         // After releasing the lock, send the notifications out.
3198         for (int i = 0; i < mTempCallbacks.size(); i++) {
3199             CallbackRecord callbackRecord = mTempCallbacks.get(i);
3200             final int uid = callbackRecord.mUid;
3201             final int pid = callbackRecord.mPid;
3202             if (isUidCached(uid)) {
3203                 // For cached apps, save the pending event until it becomes non-cached
3204                 synchronized (mPendingCallbackSelfLocked) {
3205                     SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
3206                             uid);
3207                     if (extraLogging(callbackRecord.mPackageName)) {
3208                         Slog.i(TAG, "Uid is cached: " + uid
3209                                 + ", pendingCallbacks: " + pendingCallbacks);
3210                     }
3211                     if (pendingCallbacks == null) {
3212                         pendingCallbacks = new SparseArray<>();
3213                         mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
3214                     }
3215                     PendingCallback pendingCallback = pendingCallbacks.get(pid);
3216                     if (pendingCallback == null) {
3217                         pendingCallbacks.put(pid,
3218                                 new PendingCallback(callbackRecord, displayId, event));
3219                     } else {
3220                         pendingCallback.addDisplayEvent(displayId, event);
3221                     }
3222                 }
3223             } else {
3224                 callbackRecord.notifyDisplayEventAsync(displayId, event);
3225             }
3226         }
3227         mTempCallbacks.clear();
3228     }
3229 
extraLogging(String packageName)3230     private boolean extraLogging(String packageName) {
3231         return mExtraDisplayEventLogging && mExtraDisplayLoggingPackageName.equals(packageName);
3232     }
3233 
3234     // Runs on Handler thread.
3235     // Delivers display group event notifications to callbacks.
deliverDisplayGroupEvent(int groupId, int event)3236     private void deliverDisplayGroupEvent(int groupId, int event) {
3237         if (DEBUG) {
3238             Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event="
3239                     + event);
3240         }
3241 
3242         switch (event) {
3243             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED:
3244                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
3245                     listener.onDisplayGroupAdded(groupId);
3246                 }
3247                 break;
3248 
3249             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED:
3250                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
3251                     listener.onDisplayGroupChanged(groupId);
3252                 }
3253                 break;
3254 
3255             case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED:
3256                 for (DisplayGroupListener listener : mDisplayGroupListeners) {
3257                     listener.onDisplayGroupRemoved(groupId);
3258                 }
3259                 break;
3260         }
3261     }
3262 
getProjectionService()3263     private IMediaProjectionManager getProjectionService() {
3264         if (mProjectionService == null) {
3265             mProjectionService = mInjector.getProjectionService();
3266         }
3267         return mProjectionService;
3268     }
3269 
getUserManager()3270     private UserManager getUserManager() {
3271         return mContext.getSystemService(UserManager.class);
3272     }
3273 
dumpInternal(PrintWriter pw)3274     private void dumpInternal(PrintWriter pw) {
3275         pw.println("DISPLAY MANAGER (dumpsys display)");
3276         BrightnessTracker brightnessTrackerLocal;
3277 
3278         synchronized (mSyncRoot) {
3279             brightnessTrackerLocal = mBrightnessTracker;
3280 
3281             pw.println("  mSafeMode=" + mSafeMode);
3282             pw.println("  mPendingTraversal=" + mPendingTraversal);
3283             pw.println("  mViewports=" + mViewports);
3284             pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
3285             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
3286             pw.println("  mStableDisplaySize=" + mStableDisplaySize);
3287             pw.println("  mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
3288 
3289             if (mUserPreferredMode != null) {
3290                 pw.println(" mUserPreferredMode=" + mUserPreferredMode);
3291             }
3292 
3293             pw.println();
3294             if (!mAreUserDisabledHdrTypesAllowed) {
3295                 pw.println("  mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
3296                 for (int type : mUserDisabledHdrTypes) {
3297                     pw.println("  " + type);
3298                 }
3299             }
3300 
3301             if (mHdrConversionMode != null) {
3302                 pw.println("  mHdrConversionMode=" + mHdrConversionMode);
3303             }
3304 
3305             pw.println();
3306             final int displayStateCount = mDisplayStates.size();
3307             pw.println("Display States: size=" + displayStateCount);
3308             for (int i = 0; i < displayStateCount; i++) {
3309                 final int displayId = mDisplayStates.keyAt(i);
3310                 final int displayState = mDisplayStates.valueAt(i);
3311                 final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i);
3312                 pw.println("  Display Id=" + displayId);
3313                 pw.println("  Display State=" + Display.stateToString(displayState));
3314                 pw.println("  Display Brightness=" + brightnessPair.brightness);
3315                 pw.println("  Display SdrBrightness=" + brightnessPair.sdrBrightness);
3316             }
3317 
3318             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
3319             ipw.increaseIndent();
3320 
3321             pw.println();
3322             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
3323             for (DisplayAdapter adapter : mDisplayAdapters) {
3324                 pw.println("  " + adapter.getName());
3325                 adapter.dumpLocked(ipw);
3326             }
3327 
3328             pw.println();
3329             pw.println("Display Devices: size=" + mDisplayDeviceRepo.sizeLocked());
3330             mDisplayDeviceRepo.forEachLocked(device -> {
3331                 pw.println("  " + device.getDisplayDeviceInfoLocked());
3332                 device.dumpLocked(ipw);
3333             });
3334 
3335             pw.println();
3336             mLogicalDisplayMapper.dumpLocked(pw);
3337 
3338             final int callbackCount = mCallbacks.size();
3339             pw.println();
3340             pw.println("Callbacks: size=" + callbackCount);
3341             for (int i = 0; i < callbackCount; i++) {
3342                 CallbackRecord callback = mCallbacks.valueAt(i);
3343                 pw.println("  " + i + ": mPid=" + callback.mPid
3344                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
3345             }
3346 
3347             final int displayPowerControllerCount = mDisplayPowerControllers.size();
3348             pw.println();
3349             pw.println("Display Power Controllers: size=" + displayPowerControllerCount);
3350             for (int i = 0; i < displayPowerControllerCount; i++) {
3351                 mDisplayPowerControllers.valueAt(i).dump(pw);
3352             }
3353             pw.println();
3354             mPersistentDataStore.dump(pw);
3355 
3356             final int displayWindowPolicyControllerCount = mDisplayWindowPolicyControllers.size();
3357             pw.println();
3358             pw.println("Display Window Policy Controllers: size="
3359                     + displayWindowPolicyControllerCount);
3360             for (int i = 0; i < displayWindowPolicyControllerCount; i++) {
3361                 pw.print("Display " + mDisplayWindowPolicyControllers.keyAt(i) + ":");
3362                 mDisplayWindowPolicyControllers.valueAt(i).second.dump("  ", pw);
3363             }
3364         }
3365         if (brightnessTrackerLocal != null) {
3366             pw.println();
3367             brightnessTrackerLocal.dump(pw);
3368         }
3369         pw.println();
3370         mDisplayModeDirector.dump(pw);
3371         mBrightnessSynchronizer.dump(pw);
3372         if (mSmallAreaDetectionController != null) {
3373             mSmallAreaDetectionController.dump(pw);
3374         }
3375 
3376         pw.println();
3377         mFlags.dump(pw);
3378 
3379     }
3380 
getFloatArray(TypedArray array)3381     private static float[] getFloatArray(TypedArray array) {
3382         int length = array.length();
3383         float[] floatArray = new float[length];
3384         for (int i = 0; i < length; i++) {
3385             floatArray[i] = array.getFloat(i, Float.NaN);
3386         }
3387         array.recycle();
3388         return floatArray;
3389     }
3390 
isResolutionAndRefreshRateValid(Display.Mode mode)3391     private static boolean isResolutionAndRefreshRateValid(Display.Mode mode) {
3392         return mode.getPhysicalWidth() > 0 && mode.getPhysicalHeight() > 0
3393                 && mode.getRefreshRate() > 0.0f;
3394     }
3395 
enableConnectedDisplay(int displayId, boolean enabled)3396     void enableConnectedDisplay(int displayId, boolean enabled) {
3397         synchronized (mSyncRoot) {
3398             final var logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
3399             if (logicalDisplay == null) {
3400                 Slog.w(TAG, "enableConnectedDisplay: Can not find displayId=" + displayId);
3401             } else if (ExternalDisplayPolicy.isExternalDisplayLocked(logicalDisplay)) {
3402                 mExternalDisplayPolicy.setExternalDisplayEnabledLocked(logicalDisplay, enabled);
3403             } else {
3404                 mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, enabled);
3405             }
3406         }
3407     }
3408 
requestDisplayPower(int displayId, boolean on)3409     boolean requestDisplayPower(int displayId, boolean on) {
3410         synchronized (mSyncRoot) {
3411             final var display = mLogicalDisplayMapper.getDisplayLocked(displayId);
3412             if (display == null) {
3413                 Slog.w(TAG, "requestDisplayPower: Cannot find a display with displayId="
3414                         + displayId);
3415                 return false;
3416             }
3417             final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId);
3418             var runnable = display.getPrimaryDisplayDeviceLocked().requestDisplayStateLocked(
3419                     on ? Display.STATE_ON : Display.STATE_OFF,
3420                     on ? brightnessPair.brightness : PowerManager.BRIGHTNESS_OFF_FLOAT,
3421                     brightnessPair.sdrBrightness,
3422                     display.getDisplayOffloadSessionLocked());
3423             if (runnable == null) {
3424                 Slog.w(TAG, "requestDisplayPower: Cannot update the power state to ON=" + on
3425                         + " for a display with displayId=" + displayId + ", runnable is null");
3426                 return false;
3427             }
3428             runnable.run();
3429             Slog.i(TAG, "requestDisplayPower(displayId=" + displayId + ", on=" + on + ")");
3430         }
3431         return true;
3432     }
3433 
3434     /**
3435      * This is the object that everything in the display manager locks on.
3436      * We make it an inner class within the {@link DisplayManagerService} to so that it is
3437      * clear that the object belongs to the display manager service and that it is
3438      * a unique object with a special purpose.
3439      */
3440     public static final class SyncRoot {
3441     }
3442 
3443     @VisibleForTesting
3444     static class Injector {
getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener, DisplayManagerFlags flags)3445         VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
3446                 Handler handler, DisplayAdapter.Listener displayAdapterListener,
3447                 DisplayManagerFlags flags) {
3448             return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
3449                     flags);
3450         }
3451 
getLocalDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener, DisplayManagerFlags flags, DisplayNotificationManager displayNotificationManager)3452         LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
3453                 Handler handler, DisplayAdapter.Listener displayAdapterListener,
3454                 DisplayManagerFlags flags,
3455                 DisplayNotificationManager displayNotificationManager) {
3456             return new LocalDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
3457                     flags, displayNotificationManager);
3458         }
3459 
getDefaultDisplayDelayTimeout()3460         long getDefaultDisplayDelayTimeout() {
3461             return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
3462         }
3463 
setHdrConversionMode(int conversionMode, int preferredHdrOutputType, int[] autoHdrTypes)3464         int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
3465                 int[] autoHdrTypes) {
3466             return DisplayControl.setHdrConversionMode(conversionMode, preferredHdrOutputType,
3467                     autoHdrTypes);
3468         }
3469 
3470         @Display.HdrCapabilities.HdrType
getSupportedHdrOutputTypes()3471         int[] getSupportedHdrOutputTypes() {
3472             return DisplayControl.getSupportedHdrOutputTypes();
3473         }
3474 
getHdrOutputTypesWithLatency()3475         int[] getHdrOutputTypesWithLatency() {
3476             return DisplayControl.getHdrOutputTypesWithLatency();
3477         }
3478 
getHdrOutputConversionSupport()3479         boolean getHdrOutputConversionSupport() {
3480             return DisplayControl.getHdrOutputConversionSupport();
3481         }
3482 
getProjectionService()3483         IMediaProjectionManager getProjectionService() {
3484             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
3485             return  IMediaProjectionManager.Stub.asInterface(b);
3486         }
3487 
getFlags()3488         DisplayManagerFlags getFlags() {
3489             return new DisplayManagerFlags();
3490         }
3491     }
3492 
3493     @VisibleForTesting
getDisplayDeviceInfoInternal(int displayId)3494     DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
3495         synchronized (mSyncRoot) {
3496             final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
3497             if (display != null) {
3498                 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
3499                 return displayDevice.getDisplayDeviceInfoLocked();
3500             }
3501             return null;
3502         }
3503     }
3504 
3505     @VisibleForTesting
getVirtualDisplaySurfaceInternal(IBinder appToken)3506     Surface getVirtualDisplaySurfaceInternal(IBinder appToken) {
3507         synchronized (mSyncRoot) {
3508             if (mVirtualDisplayAdapter == null) {
3509                 return null;
3510             }
3511             return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken);
3512         }
3513     }
3514 
initializeDisplayPowerControllersLocked()3515     private void initializeDisplayPowerControllersLocked() {
3516         mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
3517     }
3518 
3519     @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
addDisplayPowerControllerLocked( LogicalDisplay display)3520     private DisplayPowerControllerInterface addDisplayPowerControllerLocked(
3521             LogicalDisplay display) {
3522         if (mPowerHandler == null) {
3523             // initPowerManagement has not yet been called.
3524             return null;
3525         }
3526 
3527         if (mBrightnessTracker == null && display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) {
3528             mBrightnessTracker = new BrightnessTracker(mContext, null);
3529         }
3530 
3531         final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
3532         final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
3533                 mPersistentDataStore, display, mSyncRoot);
3534         final DisplayPowerControllerInterface displayPowerController;
3535 
3536         // If display is internal and has a HighBrightnessModeMetadata mapping, use that.
3537         // Or create a new one and use that.
3538         // We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to
3539         // displayPowerController, so the hbm info can be correctly associated
3540         // with the corresponding displaydevice.
3541         HighBrightnessModeMetadata hbmMetadata =
3542                 mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display);
3543         displayPowerController = new DisplayPowerController(
3544                 mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
3545                 mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
3546                 () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted, mFlags);
3547         mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
3548         return displayPowerController;
3549     }
3550 
handleBrightnessChange(LogicalDisplay display)3551     private void handleBrightnessChange(LogicalDisplay display) {
3552         synchronized (mSyncRoot) {
3553             sendDisplayEventIfEnabledLocked(display,
3554                     DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED);
3555         }
3556     }
3557 
getDeviceForDisplayLocked(int displayId)3558     private DisplayDevice getDeviceForDisplayLocked(int displayId) {
3559         final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
3560         return display == null ? null : display.getPrimaryDisplayDeviceLocked();
3561     }
3562 
getBrightnessConfigForDisplayWithPdsFallbackLocked( String uniqueId, int userSerial)3563     private BrightnessConfiguration getBrightnessConfigForDisplayWithPdsFallbackLocked(
3564             String uniqueId, int userSerial) {
3565         BrightnessConfiguration config =
3566                 mPersistentDataStore.getBrightnessConfigurationForDisplayLocked(
3567                         uniqueId, userSerial);
3568         if (config == null) {
3569             // Get from global configurations
3570             config = mPersistentDataStore.getBrightnessConfiguration(userSerial);
3571         }
3572         return config;
3573     }
3574 
3575     private final class DisplayManagerHandler extends Handler {
DisplayManagerHandler(Looper looper)3576         public DisplayManagerHandler(Looper looper) {
3577             super(looper, null, true /*async*/);
3578         }
3579 
3580         @Override
handleMessage(Message msg)3581         public void handleMessage(Message msg) {
3582             switch (msg.what) {
3583                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
3584                     registerDefaultDisplayAdapters();
3585                     break;
3586 
3587                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
3588                     registerAdditionalDisplayAdapters();
3589                     break;
3590 
3591                 case MSG_DELIVER_DISPLAY_EVENT:
3592                     deliverDisplayEvent(msg.arg1, null, msg.arg2);
3593                     break;
3594 
3595                 case MSG_REQUEST_TRAVERSAL:
3596                     mWindowManagerInternal.requestTraversalFromDisplayManager();
3597                     break;
3598 
3599                 case MSG_RECEIVED_DEVICE_STATE:
3600                     mWindowManagerInternal.onDisplayManagerReceivedDeviceState(msg.arg1);
3601                     break;
3602 
3603                 case MSG_UPDATE_VIEWPORT: {
3604                     final boolean changed;
3605                     synchronized (mSyncRoot) {
3606                         changed = !mTempViewports.equals(mViewports);
3607                         if (changed) {
3608                             mTempViewports.clear();
3609                             for (DisplayViewport d : mViewports) {
3610                                 mTempViewports.add(d.makeCopy());
3611                             }
3612                         }
3613                     }
3614                     if (changed) {
3615                         mInputManagerInternal.setDisplayViewports(mTempViewports);
3616                     }
3617                     break;
3618                 }
3619 
3620                 case MSG_LOAD_BRIGHTNESS_CONFIGURATIONS:
3621                     loadBrightnessConfigurations();
3622                     break;
3623 
3624                 case MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
3625                     ArraySet<Integer> uids;
3626                     synchronized (mSyncRoot) {
3627                         int displayId = msg.arg1;
3628                         final LogicalDisplay display =
3629                                 mLogicalDisplayMapper.getDisplayLocked(displayId);
3630                         if (display == null) {
3631                             break;
3632                         }
3633                         uids = display.getPendingFrameRateOverrideUids();
3634                         display.clearPendingFrameRateOverrideUids();
3635                     }
3636                     deliverDisplayEvent(msg.arg1, uids, msg.arg2);
3637                     break;
3638 
3639                 case MSG_DELIVER_DISPLAY_GROUP_EVENT:
3640                     deliverDisplayGroupEvent(msg.arg1, msg.arg2);
3641                     break;
3642 
3643             }
3644         }
3645     }
3646 
3647     private final class LogicalDisplayListener implements LogicalDisplayMapper.Listener {
3648 
3649         @GuardedBy("mSyncRoot")
3650         @Override
onLogicalDisplayEventLocked(LogicalDisplay display, int event)3651         public void onLogicalDisplayEventLocked(LogicalDisplay display, int event) {
3652             switch (event) {
3653                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED:
3654                     handleLogicalDisplayAddedLocked(display);
3655                     break;
3656 
3657                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED:
3658                     handleLogicalDisplayChangedLocked(display);
3659                     break;
3660 
3661                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED:
3662                     handleLogicalDisplayRemovedLocked(display);
3663                     break;
3664 
3665                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_SWAPPED:
3666                     handleLogicalDisplaySwappedLocked(display);
3667                     break;
3668 
3669                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
3670                     handleLogicalDisplayFrameRateOverridesChangedLocked(display);
3671                     break;
3672 
3673                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION:
3674                     handleLogicalDisplayDeviceStateTransitionLocked(display);
3675                     break;
3676 
3677                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED:
3678                     handleLogicalDisplayHdrSdrRatioChangedLocked(display);
3679                     break;
3680 
3681                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CONNECTED:
3682                     handleLogicalDisplayConnectedLocked(display);
3683                     break;
3684 
3685                 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DISCONNECTED:
3686                     handleLogicalDisplayDisconnectedLocked(display);
3687                     break;
3688             }
3689         }
3690 
3691         @Override
onDisplayGroupEventLocked(int groupId, int event)3692         public void onDisplayGroupEventLocked(int groupId, int event) {
3693             sendDisplayGroupEvent(groupId, event);
3694         }
3695 
3696         @Override
onTraversalRequested()3697         public void onTraversalRequested() {
3698             synchronized (mSyncRoot) {
3699                 scheduleTraversalLocked(false);
3700             }
3701         }
3702     }
3703 
3704     private final class CallbackRecord implements DeathRecipient {
3705         public final int mPid;
3706         public final int mUid;
3707         private final IDisplayManagerCallback mCallback;
3708         private @EventsMask AtomicLong mEventsMask;
3709         private final String mPackageName;
3710 
3711         public boolean mWifiDisplayScanRequested;
3712 
CallbackRecord(int pid, int uid, IDisplayManagerCallback callback, @EventsMask long eventsMask)3713         CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
3714                 @EventsMask long eventsMask) {
3715             mPid = pid;
3716             mUid = uid;
3717             mCallback = callback;
3718             mEventsMask = new AtomicLong(eventsMask);
3719 
3720             String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
3721             mPackageName = packageNames == null ? null : packageNames[0];
3722         }
3723 
updateEventsMask(@ventsMask long eventsMask)3724         public void updateEventsMask(@EventsMask long eventsMask) {
3725             mEventsMask.set(eventsMask);
3726         }
3727 
3728         @Override
binderDied()3729         public void binderDied() {
3730             if (DEBUG || extraLogging(mPackageName)) {
3731                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
3732             }
3733             if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
3734                 Trace.instant(Trace.TRACE_TAG_POWER,
3735                         "displayManagerBinderDied#mPid=" + mPid);
3736             }
3737             onCallbackDied(this);
3738         }
3739 
3740         /**
3741          * @return {@code false} if RemoteException happens; otherwise {@code true} for success.
3742          */
notifyDisplayEventAsync(int displayId, @DisplayEvent int event)3743         public boolean notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
3744             if (!shouldSendEvent(event)) {
3745                 if (extraLogging(mPackageName)) {
3746                     Slog.i(TAG,
3747                             "Not sending displayEvent: " + event + " due to mask:" + mEventsMask);
3748                 }
3749                 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) {
3750                     Trace.instant(Trace.TRACE_TAG_POWER,
3751                             "notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsMask="
3752                                     + mEventsMask);
3753                 }
3754                 return true;
3755             }
3756 
3757             try {
3758                 mCallback.onDisplayEvent(displayId, event);
3759                 return true;
3760             } catch (RemoteException ex) {
3761                 Slog.w(TAG, "Failed to notify process "
3762                         + mPid + " that displays changed, assuming it died.", ex);
3763                 binderDied();
3764                 return false;
3765             }
3766         }
3767 
shouldSendEvent(@isplayEvent int event)3768         private boolean shouldSendEvent(@DisplayEvent int event) {
3769             final long mask = mEventsMask.get();
3770             switch (event) {
3771                 case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
3772                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0;
3773                 case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
3774                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0;
3775                 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
3776                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0;
3777                 case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
3778                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0;
3779                 case DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED:
3780                     return (mask & DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0;
3781                 case DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED:
3782                     // fallthrough
3783                 case DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED:
3784                     return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0;
3785                 default:
3786                     // This should never happen.
3787                     Slog.e(TAG, "Unknown display event " + event);
3788                     return true;
3789             }
3790         }
3791     }
3792 
3793     private static final class PendingCallback {
3794         private final CallbackRecord mCallbackRecord;
3795         private final ArrayList<Pair<Integer, Integer>> mDisplayEvents;
3796 
PendingCallback(CallbackRecord cr, int displayId, int event)3797         PendingCallback(CallbackRecord cr, int displayId, int event) {
3798             mCallbackRecord = cr;
3799             mDisplayEvents = new ArrayList<>();
3800             mDisplayEvents.add(new Pair<>(displayId, event));
3801         }
3802 
addDisplayEvent(int displayId, int event)3803         public void addDisplayEvent(int displayId, int event) {
3804             // Ignore redundant events. Further optimization is possible by merging adjacent events.
3805             Pair<Integer, Integer> last = mDisplayEvents.get(mDisplayEvents.size() - 1);
3806             if (last.first == displayId && last.second == event) {
3807                 Slog.d(TAG,
3808                         "Ignore redundant display event " + displayId + "/" + event + " to "
3809                                 + mCallbackRecord.mUid + "/" + mCallbackRecord.mPid);
3810                 return;
3811             }
3812 
3813             mDisplayEvents.add(new Pair<>(displayId, event));
3814         }
3815 
sendPendingDisplayEvent()3816         public void sendPendingDisplayEvent() {
3817             for (int i = 0; i < mDisplayEvents.size(); i++) {
3818                 Pair<Integer, Integer> displayEvent = mDisplayEvents.get(i);
3819                 if (DEBUG) {
3820                     Slog.d(TAG, "Send pending display event #" + i + " " + displayEvent.first + "/"
3821                             + displayEvent.second + " to " + mCallbackRecord.mUid + "/"
3822                             + mCallbackRecord.mPid);
3823                 }
3824                 if (!mCallbackRecord.notifyDisplayEventAsync(displayEvent.first,
3825                         displayEvent.second)) {
3826                     Slog.d(TAG, "Drop pending events for dead process " + mCallbackRecord.mPid);
3827                     break;
3828                 }
3829             }
3830             mDisplayEvents.clear();
3831         }
3832     }
3833 
3834     @VisibleForTesting
3835     final class BinderService extends IDisplayManager.Stub {
3836         /**
3837          * Returns information about the specified logical display.
3838          *
3839          * @param displayId The logical display id.
3840          * @return The logical display info, return {@code null} if the display does not exist or
3841          * the calling UID isn't present on the display.  The returned object must be treated as
3842          * immutable.
3843          */
3844         @Override // Binder call
getDisplayInfo(int displayId)3845         public DisplayInfo getDisplayInfo(int displayId) {
3846             final int callingUid = Binder.getCallingUid();
3847             final long token = Binder.clearCallingIdentity();
3848             try {
3849                 return getDisplayInfoInternal(displayId, callingUid);
3850             } finally {
3851                 Binder.restoreCallingIdentity(token);
3852             }
3853         }
3854 
3855         /**
3856          * Returns the list of all display ids.
3857          */
3858         @Override // Binder call
getDisplayIds(boolean includeDisabled)3859         public int[] getDisplayIds(boolean includeDisabled) {
3860             final int callingUid = Binder.getCallingUid();
3861             final long token = Binder.clearCallingIdentity();
3862             try {
3863                 synchronized (mSyncRoot) {
3864                     return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid, includeDisabled);
3865                 }
3866             } finally {
3867                 Binder.restoreCallingIdentity(token);
3868             }
3869         }
3870 
3871         @Override // Binder call
isUidPresentOnDisplay(int uid, int displayId)3872         public boolean isUidPresentOnDisplay(int uid, int displayId) {
3873             final long token = Binder.clearCallingIdentity();
3874             try {
3875                 return isUidPresentOnDisplayInternal(uid, displayId);
3876             } finally {
3877                 Binder.restoreCallingIdentity(token);
3878             }
3879         }
3880 
3881         /**
3882          * Returns the stable device display size, in pixels.
3883          */
3884         @Override // Binder call
getStableDisplaySize()3885         public Point getStableDisplaySize() {
3886             final long token = Binder.clearCallingIdentity();
3887             try {
3888                 return getStableDisplaySizeInternal();
3889             } finally {
3890                 Binder.restoreCallingIdentity(token);
3891             }
3892         }
3893 
3894         @Override // Binder call
registerCallback(IDisplayManagerCallback callback)3895         public void registerCallback(IDisplayManagerCallback callback) {
3896             registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED
3897                     | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
3898                     | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
3899         }
3900 
3901         @Override // Binder call
3902         @SuppressLint("AndroidFrameworkRequiresPermission") // Permission only required sometimes
registerCallbackWithEventMask(IDisplayManagerCallback callback, @EventsMask long eventsMask)3903         public void registerCallbackWithEventMask(IDisplayManagerCallback callback,
3904                 @EventsMask long eventsMask) {
3905             if (callback == null) {
3906                 throw new IllegalArgumentException("listener must not be null");
3907             }
3908 
3909             final int callingPid = Binder.getCallingPid();
3910             final int callingUid = Binder.getCallingUid();
3911 
3912             if (mFlags.isConnectedDisplayManagementEnabled()) {
3913                 if ((eventsMask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
3914                     mContext.enforceCallingOrSelfPermission(MANAGE_DISPLAYS,
3915                             "Permission required to get signals about connection events.");
3916                 }
3917             }
3918 
3919             final long token = Binder.clearCallingIdentity();
3920             try {
3921                 registerCallbackInternal(callback, callingPid, callingUid, eventsMask);
3922             } finally {
3923                 Binder.restoreCallingIdentity(token);
3924             }
3925         }
3926 
3927         @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
3928         @Override // Binder call
startWifiDisplayScan()3929         public void startWifiDisplayScan() {
3930             startWifiDisplayScan_enforcePermission();
3931 
3932             final int callingPid = Binder.getCallingPid();
3933             final long token = Binder.clearCallingIdentity();
3934             try {
3935                 startWifiDisplayScanInternal(callingPid);
3936             } finally {
3937                 Binder.restoreCallingIdentity(token);
3938             }
3939         }
3940 
3941         @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
3942         @Override // Binder call
stopWifiDisplayScan()3943         public void stopWifiDisplayScan() {
3944             stopWifiDisplayScan_enforcePermission();
3945 
3946             final int callingPid = Binder.getCallingPid();
3947             final long token = Binder.clearCallingIdentity();
3948             try {
3949                 stopWifiDisplayScanInternal(callingPid);
3950             } finally {
3951                 Binder.restoreCallingIdentity(token);
3952             }
3953         }
3954 
3955         @Override // Binder call
connectWifiDisplay(String address)3956         public void connectWifiDisplay(String address) {
3957             if (address == null) {
3958                 throw new IllegalArgumentException("address must not be null");
3959             }
3960             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
3961                     "Permission required to connect to a wifi display");
3962 
3963             final long token = Binder.clearCallingIdentity();
3964             try {
3965                 connectWifiDisplayInternal(address);
3966             } finally {
3967                 Binder.restoreCallingIdentity(token);
3968             }
3969         }
3970 
3971         @Override // Binder call
disconnectWifiDisplay()3972         public void disconnectWifiDisplay() {
3973             // This request does not require special permissions.
3974             // Any app can request disconnection from the currently active wifi display.
3975             // This exception should no longer be needed once wifi display control moves
3976             // to the media router service.
3977 
3978             final long token = Binder.clearCallingIdentity();
3979             try {
3980                 disconnectWifiDisplayInternal();
3981             } finally {
3982                 Binder.restoreCallingIdentity(token);
3983             }
3984         }
3985 
3986         @Override // Binder call
renameWifiDisplay(String address, String alias)3987         public void renameWifiDisplay(String address, String alias) {
3988             if (address == null) {
3989                 throw new IllegalArgumentException("address must not be null");
3990             }
3991             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
3992                     "Permission required to rename to a wifi display");
3993 
3994             final long token = Binder.clearCallingIdentity();
3995             try {
3996                 renameWifiDisplayInternal(address, alias);
3997             } finally {
3998                 Binder.restoreCallingIdentity(token);
3999             }
4000         }
4001 
4002         @Override // Binder call
forgetWifiDisplay(String address)4003         public void forgetWifiDisplay(String address) {
4004             if (address == null) {
4005                 throw new IllegalArgumentException("address must not be null");
4006             }
4007             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
4008                     "Permission required to forget to a wifi display");
4009 
4010             final long token = Binder.clearCallingIdentity();
4011             try {
4012                 forgetWifiDisplayInternal(address);
4013             } finally {
4014                 Binder.restoreCallingIdentity(token);
4015             }
4016         }
4017 
4018         @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
4019         @Override // Binder call
pauseWifiDisplay()4020         public void pauseWifiDisplay() {
4021             pauseWifiDisplay_enforcePermission();
4022 
4023             final long token = Binder.clearCallingIdentity();
4024             try {
4025                 pauseWifiDisplayInternal();
4026             } finally {
4027                 Binder.restoreCallingIdentity(token);
4028             }
4029         }
4030 
4031         @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
4032         @Override // Binder call
resumeWifiDisplay()4033         public void resumeWifiDisplay() {
4034             resumeWifiDisplay_enforcePermission();
4035 
4036             final long token = Binder.clearCallingIdentity();
4037             try {
4038                 resumeWifiDisplayInternal();
4039             } finally {
4040                 Binder.restoreCallingIdentity(token);
4041             }
4042         }
4043 
4044         @Override // Binder call
getWifiDisplayStatus()4045         public WifiDisplayStatus getWifiDisplayStatus() {
4046             // This request does not require special permissions.
4047             // Any app can get information about available wifi displays.
4048 
4049             final long token = Binder.clearCallingIdentity();
4050             try {
4051                 return getWifiDisplayStatusInternal();
4052             } finally {
4053                 Binder.restoreCallingIdentity(token);
4054             }
4055         }
4056 
4057         @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
4058         @Override // Binder call
setUserDisabledHdrTypes(int[] userDisabledFormats)4059         public void setUserDisabledHdrTypes(int[] userDisabledFormats) {
4060             setUserDisabledHdrTypes_enforcePermission();
4061 
4062             final long token = Binder.clearCallingIdentity();
4063             try {
4064                 setUserDisabledHdrTypesInternal(userDisabledFormats);
4065             } finally {
4066                 Binder.restoreCallingIdentity(token);
4067             }
4068         }
4069 
4070         @Override
overrideHdrTypes(int displayId, int[] modes)4071         public void overrideHdrTypes(int displayId, int[] modes) {
4072             IBinder displayToken;
4073             synchronized (mSyncRoot) {
4074                 displayToken = getDisplayToken(displayId);
4075                 if (displayToken == null) {
4076                     throw new IllegalArgumentException("Invalid display: " + displayId);
4077                 }
4078             }
4079 
4080             DisplayControl.overrideHdrTypes(displayToken, modes);
4081         }
4082 
4083         @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
4084         @Override // Binder call
setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed)4085         public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) {
4086             setAreUserDisabledHdrTypesAllowed_enforcePermission();
4087             final long token = Binder.clearCallingIdentity();
4088             try {
4089                 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed);
4090             } finally {
4091                 Binder.restoreCallingIdentity(token);
4092             }
4093         }
4094 
4095         @Override // Binder call
areUserDisabledHdrTypesAllowed()4096         public boolean areUserDisabledHdrTypesAllowed() {
4097             synchronized (mSyncRoot) {
4098                 return mAreUserDisabledHdrTypesAllowed;
4099             }
4100         }
4101 
4102         @Override // Binder call
getUserDisabledHdrTypes()4103         public int[] getUserDisabledHdrTypes() {
4104             synchronized (mSyncRoot) {
4105                 return mUserDisabledHdrTypes;
4106             }
4107         }
4108 
4109         @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE)
4110         @Override // Binder call
requestColorMode(int displayId, int colorMode)4111         public void requestColorMode(int displayId, int colorMode) {
4112             requestColorMode_enforcePermission();
4113             final long token = Binder.clearCallingIdentity();
4114             try {
4115                 requestColorModeInternal(displayId, colorMode);
4116             } finally {
4117                 Binder.restoreCallingIdentity(token);
4118             }
4119         }
4120 
4121         @Override // Binder call
createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, String packageName)4122         public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
4123                 IVirtualDisplayCallback callback, IMediaProjection projection,
4124                 String packageName) {
4125             return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
4126                     null, null, packageName);
4127         }
4128 
4129         @Override // Binder call
resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)4130         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
4131                 int width, int height, int densityDpi) {
4132             if (width <= 0 || height <= 0 || densityDpi <= 0) {
4133                 throw new IllegalArgumentException("width, height, and densityDpi must be "
4134                         + "greater than 0");
4135             }
4136             final long token = Binder.clearCallingIdentity();
4137             try {
4138                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
4139             } finally {
4140                 Binder.restoreCallingIdentity(token);
4141             }
4142         }
4143 
4144         @Override // Binder call
setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)4145         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
4146             if (surface != null && surface.isSingleBuffered()) {
4147                 throw new IllegalArgumentException("Surface can't be single-buffered");
4148             }
4149             final long token = Binder.clearCallingIdentity();
4150             try {
4151                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
4152             } finally {
4153                 Binder.restoreCallingIdentity(token);
4154             }
4155         }
4156 
4157         @Override // Binder call
releaseVirtualDisplay(IVirtualDisplayCallback callback)4158         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
4159             final long token = Binder.clearCallingIdentity();
4160             try {
4161                 releaseVirtualDisplayInternal(callback.asBinder());
4162             } finally {
4163                 Binder.restoreCallingIdentity(token);
4164             }
4165         }
4166 
4167         @Override // Binder call
setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn)4168         public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) {
4169             final long token = Binder.clearCallingIdentity();
4170             try {
4171                 setVirtualDisplayStateInternal(callback.asBinder(), isOn);
4172             } finally {
4173                 Binder.restoreCallingIdentity(token);
4174             }
4175         }
4176 
4177         @Override // Binder call
dump(@onNull FileDescriptor fd, @NonNull final PrintWriter pw, String[] args)4178         public void dump(@NonNull FileDescriptor fd, @NonNull final PrintWriter pw, String[] args) {
4179             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
4180 
4181             final long token = Binder.clearCallingIdentity();
4182             try {
4183                 dumpInternal(pw);
4184             } finally {
4185                 Binder.restoreCallingIdentity(token);
4186             }
4187         }
4188 
4189         @EnforcePermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
4190         @Override // Binder call
getBrightnessEvents(String callingPackage)4191         public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
4192             getBrightnessEvents_enforcePermission();
4193 
4194             final int callingUid = Binder.getCallingUid();
4195             AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
4196             final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
4197                     callingUid, callingPackage);
4198             final boolean hasUsageStats;
4199             if (mode == AppOpsManager.MODE_DEFAULT) {
4200                 // The default behavior here is to check if PackageManager has given the app
4201                 // permission.
4202                 hasUsageStats = mContext.checkCallingPermission(
4203                         Manifest.permission.PACKAGE_USAGE_STATS)
4204                         == PackageManager.PERMISSION_GRANTED;
4205             } else {
4206                 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED;
4207             }
4208 
4209             final int userId = UserHandle.getUserId(callingUid);
4210             final long token = Binder.clearCallingIdentity();
4211             try {
4212                 synchronized (mSyncRoot) {
4213                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4214                             .getBrightnessEvents(userId, hasUsageStats);
4215                 }
4216             } finally {
4217                 Binder.restoreCallingIdentity(token);
4218             }
4219         }
4220 
4221         @EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS)
4222         @Override // Binder call
getAmbientBrightnessStats()4223         public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
4224             getAmbientBrightnessStats_enforcePermission();
4225             final int callingUid = Binder.getCallingUid();
4226             final int userId = UserHandle.getUserId(callingUid);
4227             final long token = Binder.clearCallingIdentity();
4228             try {
4229                 synchronized (mSyncRoot) {
4230                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4231                             .getAmbientBrightnessStats(userId);
4232                 }
4233             } finally {
4234                 Binder.restoreCallingIdentity(token);
4235             }
4236         }
4237 
4238         @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
4239         @Override // Binder call
setBrightnessConfigurationForUser( BrightnessConfiguration c, @UserIdInt int userId, String packageName)4240         public void setBrightnessConfigurationForUser(
4241                 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
4242             setBrightnessConfigurationForUser_enforcePermission();
4243             if (userId != UserHandle.getCallingUserId()) {
4244                 mContext.enforceCallingOrSelfPermission(
4245                         Manifest.permission.INTERACT_ACROSS_USERS,
4246                         "Permission required to change the display brightness"
4247                                 + " configuration of another user");
4248             }
4249             final long token = Binder.clearCallingIdentity();
4250             try {
4251                 synchronized (mSyncRoot) {
4252                     mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
4253                         if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
4254                             return;
4255                         }
4256                         final DisplayDevice displayDevice =
4257                                 logicalDisplay.getPrimaryDisplayDeviceLocked();
4258                         setBrightnessConfigurationForDisplayInternal(c, displayDevice.getUniqueId(),
4259                                 userId, packageName);
4260                     });
4261                 }
4262             } finally {
4263                 Binder.restoreCallingIdentity(token);
4264             }
4265         }
4266 
4267         @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
4268         @Override // Binder call
setBrightnessConfigurationForDisplay(BrightnessConfiguration c, String uniqueId, int userId, String packageName)4269         public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c,
4270                 String uniqueId, int userId, String packageName) {
4271             setBrightnessConfigurationForDisplay_enforcePermission();
4272             if (userId != UserHandle.getCallingUserId()) {
4273                 mContext.enforceCallingOrSelfPermission(
4274                         Manifest.permission.INTERACT_ACROSS_USERS,
4275                         "Permission required to change the display brightness"
4276                                 + " configuration of another user");
4277             }
4278             final long token = Binder.clearCallingIdentity();
4279             try {
4280                 setBrightnessConfigurationForDisplayInternal(c, uniqueId, userId, packageName);
4281             } finally {
4282                 Binder.restoreCallingIdentity(token);
4283             }
4284         }
4285 
4286         @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
4287         @Override // Binder call
getBrightnessConfigurationForDisplay(String uniqueId, int userId)4288         public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId,
4289                 int userId) {
4290             getBrightnessConfigurationForDisplay_enforcePermission();
4291             if (userId != UserHandle.getCallingUserId()) {
4292                 mContext.enforceCallingOrSelfPermission(
4293                         Manifest.permission.INTERACT_ACROSS_USERS,
4294                         "Permission required to read the display brightness"
4295                                 + " configuration of another user");
4296             }
4297             final long token = Binder.clearCallingIdentity();
4298             final int userSerial = getUserManager().getUserSerialNumber(userId);
4299             try {
4300                 synchronized (mSyncRoot) {
4301                     // Get from per-display configurations
4302                     BrightnessConfiguration config =
4303                             getBrightnessConfigForDisplayWithPdsFallbackLocked(
4304                                     uniqueId, userSerial);
4305                     if (config == null) {
4306                         // Get default configuration
4307                         DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
4308                         if (dpc != null) {
4309                             config = dpc.getDefaultBrightnessConfiguration();
4310                         }
4311                     }
4312                     return config;
4313                 }
4314             } finally {
4315                 Binder.restoreCallingIdentity(token);
4316             }
4317         }
4318 
4319 
4320 
4321         @Override // Binder call
getBrightnessConfigurationForUser(int userId)4322         public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
4323             final String uniqueId;
4324             synchronized (mSyncRoot) {
4325                 DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked(
4326                         Display.DEFAULT_DISPLAY).getPrimaryDisplayDeviceLocked();
4327                 uniqueId = displayDevice.getUniqueId();
4328             }
4329             return getBrightnessConfigurationForDisplay(uniqueId, userId);
4330 
4331 
4332         }
4333 
4334         @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS)
4335         @Override // Binder call
getDefaultBrightnessConfiguration()4336         public BrightnessConfiguration getDefaultBrightnessConfiguration() {
4337             getDefaultBrightnessConfiguration_enforcePermission();
4338             final long token = Binder.clearCallingIdentity();
4339             try {
4340                 synchronized (mSyncRoot) {
4341                     return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4342                             .getDefaultBrightnessConfiguration();
4343                 }
4344             } finally {
4345                 Binder.restoreCallingIdentity(token);
4346             }
4347         }
4348 
4349         @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
4350         @Override
getBrightnessInfo(int displayId)4351         public BrightnessInfo getBrightnessInfo(int displayId) {
4352             getBrightnessInfo_enforcePermission();
4353             final long token = Binder.clearCallingIdentity();
4354             try {
4355                 synchronized (mSyncRoot) {
4356                     LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(
4357                             displayId, /* includeDisabled= */ false);
4358                     if (display == null || !display.isEnabledLocked()) {
4359                         return null;
4360                     }
4361                     DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
4362                     if (dpc != null) {
4363                         return dpc.getBrightnessInfo();
4364                     }
4365                 }
4366             } finally {
4367                 Binder.restoreCallingIdentity(token);
4368             }
4369             return null;
4370         }
4371 
4372         @Override // Binder call
isMinimalPostProcessingRequested(int displayId)4373         public boolean isMinimalPostProcessingRequested(int displayId) {
4374             synchronized (mSyncRoot) {
4375                 return mLogicalDisplayMapper.getDisplayLocked(displayId)
4376                         .getRequestedMinimalPostProcessingLocked();
4377             }
4378         }
4379 
4380         @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
4381         @Override // Binder call
setTemporaryBrightness(int displayId, float brightness)4382         public void setTemporaryBrightness(int displayId, float brightness) {
4383             setTemporaryBrightness_enforcePermission();
4384             final long token = Binder.clearCallingIdentity();
4385             try {
4386                 synchronized (mSyncRoot) {
4387                     mDisplayPowerControllers.get(displayId)
4388                             .setTemporaryBrightness(brightness);
4389                 }
4390             } finally {
4391                 Binder.restoreCallingIdentity(token);
4392             }
4393         }
4394 
4395         @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
4396         @Override // Binder call
setBrightness(int displayId, float brightness)4397         public void setBrightness(int displayId, float brightness) {
4398             setBrightness_enforcePermission();
4399             if (!isValidBrightness(brightness)) {
4400                 Slog.w(TAG, "Attempted to set invalid brightness" + brightness);
4401                 return;
4402             }
4403             final long token = Binder.clearCallingIdentity();
4404             try {
4405                 synchronized (mSyncRoot) {
4406                     DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
4407                     if (dpc != null) {
4408                         dpc.setBrightness(brightness);
4409                     }
4410                     mPersistentDataStore.saveIfNeeded();
4411                 }
4412             } finally {
4413                 Binder.restoreCallingIdentity(token);
4414             }
4415         }
4416 
4417         @Override // Binder call
getBrightness(int displayId)4418         public float getBrightness(int displayId) {
4419             float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
4420             mContext.enforceCallingOrSelfPermission(
4421                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
4422                     "Permission required to set the display's brightness");
4423             final long token = Binder.clearCallingIdentity();
4424             try {
4425                 synchronized (mSyncRoot) {
4426                     DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
4427                     if (dpc != null) {
4428                         brightness = dpc.getScreenBrightnessSetting();
4429                     }
4430                 }
4431             } finally {
4432                 Binder.restoreCallingIdentity(token);
4433             }
4434             return brightness;
4435         }
4436 
4437         @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
4438         @Override // Binder call
setTemporaryAutoBrightnessAdjustment(float adjustment)4439         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
4440             setTemporaryAutoBrightnessAdjustment_enforcePermission();
4441             final long token = Binder.clearCallingIdentity();
4442             try {
4443                 synchronized (mSyncRoot) {
4444                     mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4445                             .setTemporaryAutoBrightnessAdjustment(adjustment);
4446                 }
4447             } finally {
4448                 Binder.restoreCallingIdentity(token);
4449             }
4450         }
4451 
4452         @Override // Binder call
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, @NonNull String[] args, ShellCallback callback, @NonNull ResultReceiver resultReceiver)4453         public void onShellCommand(FileDescriptor in, FileDescriptor out,
4454                 FileDescriptor err, @NonNull String[] args, ShellCallback callback,
4455                 @NonNull ResultReceiver resultReceiver) {
4456             new DisplayManagerShellCommand(DisplayManagerService.this, mFlags).exec(this, in, out,
4457                     err, args, callback, resultReceiver);
4458         }
4459 
4460         @Override // Binder call
getMinimumBrightnessCurve()4461         public Curve getMinimumBrightnessCurve() {
4462             final long token = Binder.clearCallingIdentity();
4463             try {
4464                 return getMinimumBrightnessCurveInternal();
4465             } finally {
4466                 Binder.restoreCallingIdentity(token);
4467             }
4468         }
4469 
4470         @Override // Binder call
getPreferredWideGamutColorSpaceId()4471         public int getPreferredWideGamutColorSpaceId() {
4472             final long token = Binder.clearCallingIdentity();
4473             try {
4474                 return getPreferredWideGamutColorSpaceIdInternal();
4475             } finally {
4476                 Binder.restoreCallingIdentity(token);
4477             }
4478         }
4479 
4480         @EnforcePermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE)
4481         @Override // Binder call
setUserPreferredDisplayMode(int displayId, Display.Mode mode)4482         public void setUserPreferredDisplayMode(int displayId, Display.Mode mode) {
4483             setUserPreferredDisplayMode_enforcePermission();
4484             final long token = Binder.clearCallingIdentity();
4485             try {
4486                 setUserPreferredDisplayModeInternal(displayId, mode);
4487             } finally {
4488                 Binder.restoreCallingIdentity(token);
4489             }
4490         }
4491 
4492         @Override // Binder call
getUserPreferredDisplayMode(int displayId)4493         public Display.Mode getUserPreferredDisplayMode(int displayId) {
4494             final long token = Binder.clearCallingIdentity();
4495             try {
4496                 return getUserPreferredDisplayModeInternal(displayId);
4497             } finally {
4498                 Binder.restoreCallingIdentity(token);
4499             }
4500         }
4501 
4502         @Override // Binder call
getSystemPreferredDisplayMode(int displayId)4503         public Display.Mode getSystemPreferredDisplayMode(int displayId) {
4504             final long token = Binder.clearCallingIdentity();
4505             try {
4506                 return getSystemPreferredDisplayModeInternal(displayId);
4507             } finally {
4508                 Binder.restoreCallingIdentity(token);
4509             }
4510         }
4511 
4512         @Override // Binder call
setHdrConversionMode(HdrConversionMode hdrConversionMode)4513         public void setHdrConversionMode(HdrConversionMode hdrConversionMode) {
4514             if (!mIsHdrOutputControlEnabled) {
4515                 return;
4516             }
4517             mContext.enforceCallingOrSelfPermission(
4518                     Manifest.permission.MODIFY_HDR_CONVERSION_MODE,
4519                     "Permission required to set the HDR conversion mode.");
4520             final long token = Binder.clearCallingIdentity();
4521             try {
4522                 setHdrConversionModeInternal(hdrConversionMode);
4523             } finally {
4524                 Binder.restoreCallingIdentity(token);
4525             }
4526         }
4527 
4528         @Override // Binder call
getHdrConversionModeSetting()4529         public HdrConversionMode getHdrConversionModeSetting() {
4530             if (!mIsHdrOutputControlEnabled) {
4531                 return HDR_CONVERSION_MODE_UNSUPPORTED;
4532             }
4533             final long token = Binder.clearCallingIdentity();
4534             try {
4535                 return getHdrConversionModeSettingInternal();
4536             } finally {
4537                 Binder.restoreCallingIdentity(token);
4538             }
4539         }
4540 
4541         @Override // Binder call
getHdrConversionMode()4542         public HdrConversionMode getHdrConversionMode() {
4543             if (!mIsHdrOutputControlEnabled) {
4544                 return HDR_CONVERSION_MODE_UNSUPPORTED;
4545             }
4546             final long token = Binder.clearCallingIdentity();
4547             try {
4548                 return getHdrConversionModeInternal();
4549             } finally {
4550                 Binder.restoreCallingIdentity(token);
4551             }
4552         }
4553 
4554         @Display.HdrCapabilities.HdrType
4555         @Override // Binder call
getSupportedHdrOutputTypes()4556         public int[] getSupportedHdrOutputTypes() {
4557             if (!mIsHdrOutputControlEnabled) {
4558                 return EMPTY_ARRAY;
4559             }
4560             final long token = Binder.clearCallingIdentity();
4561             try {
4562                 return getSupportedHdrOutputTypesInternal();
4563             } finally {
4564                 Binder.restoreCallingIdentity(token);
4565             }
4566         }
4567 
4568         @EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
4569         @Override // Binder call
setShouldAlwaysRespectAppRequestedMode(boolean enabled)4570         public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
4571             setShouldAlwaysRespectAppRequestedMode_enforcePermission();
4572             final long token = Binder.clearCallingIdentity();
4573             try {
4574                 setShouldAlwaysRespectAppRequestedModeInternal(enabled);
4575             } finally {
4576                 Binder.restoreCallingIdentity(token);
4577             }
4578         }
4579 
4580         @EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
4581         @Override // Binder call
shouldAlwaysRespectAppRequestedMode()4582         public boolean shouldAlwaysRespectAppRequestedMode() {
4583             shouldAlwaysRespectAppRequestedMode_enforcePermission();
4584             final long token = Binder.clearCallingIdentity();
4585             try {
4586                 return shouldAlwaysRespectAppRequestedModeInternal();
4587             } finally {
4588                 Binder.restoreCallingIdentity(token);
4589             }
4590         }
4591 
4592         @EnforcePermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
4593         @Override // Binder call
setRefreshRateSwitchingType(int newValue)4594         public void setRefreshRateSwitchingType(int newValue) {
4595             setRefreshRateSwitchingType_enforcePermission();
4596             final long token = Binder.clearCallingIdentity();
4597             try {
4598                 setRefreshRateSwitchingTypeInternal(newValue);
4599             } finally {
4600                 Binder.restoreCallingIdentity(token);
4601             }
4602         }
4603 
4604         @Override // Binder call
getRefreshRateSwitchingType()4605         public int getRefreshRateSwitchingType() {
4606             final long token = Binder.clearCallingIdentity();
4607             try {
4608                 return getRefreshRateSwitchingTypeInternal();
4609             } finally {
4610                 Binder.restoreCallingIdentity(token);
4611             }
4612         }
4613 
4614         @Override // Binder call
getDisplayDecorationSupport(int displayId)4615         public DisplayDecorationSupport getDisplayDecorationSupport(int displayId) {
4616             final long token = Binder.clearCallingIdentity();
4617             try {
4618                 return getDisplayDecorationSupportInternal(displayId);
4619             } finally {
4620                 Binder.restoreCallingIdentity(token);
4621             }
4622         }
4623 
4624         @Override
setDisplayIdToMirror(IBinder token, int displayId)4625         public void setDisplayIdToMirror(IBinder token, int displayId) {
4626             synchronized (mSyncRoot) {
4627                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
4628                 if (mVirtualDisplayAdapter != null) {
4629                     mVirtualDisplayAdapter.setDisplayIdToMirror(token,
4630                             display == null ? Display.INVALID_DISPLAY : displayId);
4631                 }
4632             }
4633         }
4634 
4635         @Override
getOverlaySupport()4636         public OverlayProperties getOverlaySupport() {
4637             final long token = Binder.clearCallingIdentity();
4638             try {
4639                 return getOverlaySupportInternal();
4640             } finally {
4641                 Binder.restoreCallingIdentity(token);
4642             }
4643         }
4644 
4645         @EnforcePermission(MANAGE_DISPLAYS)
enableConnectedDisplay(int displayId)4646         public void enableConnectedDisplay(int displayId) {
4647             enableConnectedDisplay_enforcePermission();
4648             DisplayManagerService.this.enableConnectedDisplay(displayId, true);
4649         }
4650 
4651         @EnforcePermission(MANAGE_DISPLAYS)
disableConnectedDisplay(int displayId)4652         public void disableConnectedDisplay(int displayId) {
4653             disableConnectedDisplay_enforcePermission();
4654             DisplayManagerService.this.enableConnectedDisplay(displayId, false);
4655         }
4656 
4657         @EnforcePermission(MANAGE_DISPLAYS)
requestDisplayPower(int displayId, boolean on)4658         public boolean requestDisplayPower(int displayId, boolean on) {
4659             requestDisplayPower_enforcePermission();
4660             return DisplayManagerService.this.requestDisplayPower(displayId, on);
4661         }
4662 
4663         @EnforcePermission(RESTRICT_DISPLAY_MODES)
4664         @Override // Binder call
requestDisplayModes(IBinder token, int displayId, @Nullable int[] modeIds)4665         public void requestDisplayModes(IBinder token, int displayId, @Nullable int[] modeIds) {
4666             requestDisplayModes_enforcePermission();
4667             DisplayManagerService.this.mDisplayModeDirector.requestDisplayModes(
4668                     token, displayId, modeIds);
4669         }
4670     }
4671 
isValidBrightness(float brightness)4672     private static boolean isValidBrightness(float brightness) {
4673         return !Float.isNaN(brightness)
4674                 && (brightness >= PowerManager.BRIGHTNESS_MIN)
4675                 && (brightness <= PowerManager.BRIGHTNESS_MAX);
4676     }
4677 
4678     @VisibleForTesting
overrideSensorManager(SensorManager sensorManager)4679     void overrideSensorManager(SensorManager sensorManager) {
4680         synchronized (mSyncRoot) {
4681             mSensorManager = sensorManager;
4682         }
4683     }
4684 
4685     @VisibleForTesting
4686     final class LocalService extends DisplayManagerInternal {
4687 
4688         @Override
initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)4689         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
4690                 SensorManager sensorManager) {
4691             synchronized (mSyncRoot) {
4692                 mDisplayPowerCallbacks = callbacks;
4693                 mSensorManager = sensorManager;
4694                 mPowerHandler = handler;
4695                 initializeDisplayPowerControllersLocked();
4696             }
4697 
4698             mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS);
4699         }
4700 
4701         @Override
createVirtualDisplay(VirtualDisplayConfig config, IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName)4702         public int createVirtualDisplay(VirtualDisplayConfig config,
4703                 IVirtualDisplayCallback callback, IVirtualDevice virtualDevice,
4704                 DisplayWindowPolicyController dwpc, String packageName) {
4705             return createVirtualDisplayInternal(config, callback, null, virtualDevice, dwpc,
4706                     packageName);
4707         }
4708 
4709         @Override
requestPowerState(int groupId, DisplayPowerRequest request, boolean waitForNegativeProximity)4710         public boolean requestPowerState(int groupId, DisplayPowerRequest request,
4711                 boolean waitForNegativeProximity) {
4712             synchronized (mSyncRoot) {
4713                 final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked(
4714                         groupId);
4715                 if (displayGroup == null) {
4716                     return true;
4717                 }
4718 
4719                 final int size = displayGroup.getSizeLocked();
4720                 boolean ready = true;
4721                 for (int i = 0; i < size; i++) {
4722                     final int id = displayGroup.getIdLocked(i);
4723                     final DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked(
4724                             id).getPrimaryDisplayDeviceLocked();
4725                     final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
4726                     if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
4727                         final DisplayPowerControllerInterface displayPowerController =
4728                                 mDisplayPowerControllers.get(id);
4729                         if (displayPowerController != null) {
4730                             ready &= displayPowerController.requestPowerState(request,
4731                                     waitForNegativeProximity);
4732                         }
4733                     }
4734                 }
4735 
4736                 return ready;
4737             }
4738         }
4739 
4740         @Override
isProximitySensorAvailable()4741         public boolean isProximitySensorAvailable() {
4742             synchronized (mSyncRoot) {
4743                 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4744                         .isProximitySensorAvailable();
4745             }
4746         }
4747 
4748         @Override
registerDisplayGroupListener(DisplayGroupListener listener)4749         public void registerDisplayGroupListener(DisplayGroupListener listener) {
4750             mDisplayGroupListeners.add(listener);
4751         }
4752 
4753         @Override
unregisterDisplayGroupListener(DisplayGroupListener listener)4754         public void unregisterDisplayGroupListener(DisplayGroupListener listener) {
4755             mDisplayGroupListeners.remove(listener);
4756         }
4757 
4758         @Override
systemScreenshot(int displayId)4759         public ScreenCapture.ScreenshotHardwareBuffer systemScreenshot(int displayId) {
4760             return systemScreenshotInternal(displayId);
4761         }
4762 
4763         @Override
userScreenshot(int displayId)4764         public ScreenCapture.ScreenshotHardwareBuffer userScreenshot(int displayId) {
4765             return userScreenshotInternal(displayId);
4766         }
4767 
4768         @Override
getDisplayInfo(int displayId)4769         public DisplayInfo getDisplayInfo(int displayId) {
4770             return getDisplayInfoInternal(displayId, Process.myUid());
4771         }
4772 
4773         @Override
getPossibleDisplayInfo(int displayId)4774         public Set<DisplayInfo> getPossibleDisplayInfo(int displayId) {
4775             synchronized (mSyncRoot) {
4776                 Set<DisplayInfo> possibleInfo = new ArraySet<>();
4777                 // For each of supported device states, retrieve the display layout of that state,
4778                 // and return all of the DisplayInfos (one per state) for the given display id.
4779                 if (mDeviceStateManager == null) {
4780                     Slog.w(TAG, "Can't get supported states since DeviceStateManager not ready");
4781                     return possibleInfo;
4782                 }
4783                 final int[] supportedStates =
4784                         mDeviceStateManager.getSupportedStateIdentifiers();
4785                 // TODO(b/352019542): remove the log once b/345960547 is fixed.
4786                 Slog.d(TAG, "supportedStates=" + Arrays.toString(supportedStates));
4787                 DisplayInfo displayInfo;
4788                 for (int state : supportedStates) {
4789                     displayInfo = mLogicalDisplayMapper.getDisplayInfoForStateLocked(state,
4790                             displayId);
4791                     if (displayInfo != null) {
4792                         possibleInfo.add(displayInfo);
4793                     }
4794                 }
4795                 // TODO(b/352019542): remove the log once b/345960547 is fixed.
4796                 Slog.d(TAG, "possibleInfos=" + possibleInfo);
4797                 return possibleInfo;
4798             }
4799         }
4800 
4801         @Override
getDisplayPosition(int displayId)4802         public Point getDisplayPosition(int displayId) {
4803             synchronized (mSyncRoot) {
4804                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
4805                 if (display != null) {
4806                     return display.getDisplayPosition();
4807                 }
4808                 return null;
4809             }
4810         }
4811 
4812         @Override
registerDisplayTransactionListener(DisplayTransactionListener listener)4813         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
4814             if (listener == null) {
4815                 throw new IllegalArgumentException("listener must not be null");
4816             }
4817 
4818             registerDisplayTransactionListenerInternal(listener);
4819         }
4820 
4821         @Override
unregisterDisplayTransactionListener(DisplayTransactionListener listener)4822         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
4823             if (listener == null) {
4824                 throw new IllegalArgumentException("listener must not be null");
4825             }
4826 
4827             unregisterDisplayTransactionListenerInternal(listener);
4828         }
4829 
4830         @Override
setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)4831         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
4832             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
4833         }
4834 
4835         @Override
getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo)4836         public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
4837             getNonOverrideDisplayInfoInternal(displayId, outInfo);
4838         }
4839 
4840         @Override
performTraversal(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)4841         public void performTraversal(SurfaceControl.Transaction t,
4842                 SparseArray<SurfaceControl.Transaction> displayTransactions) {
4843             performTraversalInternal(t, displayTransactions);
4844         }
4845 
4846         @Override
setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate, float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing, boolean disableHdrConversion, boolean inTraversal)4847         public void setDisplayProperties(int displayId, boolean hasContent,
4848                 float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate,
4849                 float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,
4850                 boolean disableHdrConversion, boolean inTraversal) {
4851             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
4852                     requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate,
4853                     requestedMinimalPostProcessing, disableHdrConversion, inTraversal);
4854         }
4855 
4856         @Override
setDisplayOffsets(int displayId, int x, int y)4857         public void setDisplayOffsets(int displayId, int x, int y) {
4858             setDisplayOffsetsInternal(displayId, x, y);
4859         }
4860 
4861         @Override
setDisplayScalingDisabled(int displayId, boolean disableScaling)4862         public void setDisplayScalingDisabled(int displayId, boolean disableScaling) {
4863             setDisplayScalingDisabledInternal(displayId, disableScaling);
4864         }
4865 
4866         @Override
setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs)4867         public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
4868             setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
4869         }
4870 
4871         @Override
persistBrightnessTrackerState()4872         public void persistBrightnessTrackerState() {
4873             synchronized (mSyncRoot) {
4874                 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4875                         .persistBrightnessTrackerState();
4876             }
4877         }
4878 
4879         @Override
onOverlayChanged()4880         public void onOverlayChanged() {
4881             synchronized (mSyncRoot) {
4882                 mDisplayDeviceRepo.forEachLocked(DisplayDevice::onOverlayChangedLocked);
4883             }
4884         }
4885 
4886         @Override
getDisplayedContentSamplingAttributes( int displayId)4887         public DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributes(
4888                 int displayId) {
4889             return getDisplayedContentSamplingAttributesInternal(displayId);
4890         }
4891 
4892         @Override
setDisplayedContentSamplingEnabled( int displayId, boolean enable, int componentMask, int maxFrames)4893         public boolean setDisplayedContentSamplingEnabled(
4894                 int displayId, boolean enable, int componentMask, int maxFrames) {
4895             return setDisplayedContentSamplingEnabledInternal(
4896                     displayId, enable, componentMask, maxFrames);
4897         }
4898 
4899         @Override
getDisplayedContentSample(int displayId, long maxFrames, long timestamp)4900         public DisplayedContentSample getDisplayedContentSample(int displayId,
4901                 long maxFrames, long timestamp) {
4902             return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp);
4903         }
4904 
4905         @Override
ignoreProximitySensorUntilChanged()4906         public void ignoreProximitySensorUntilChanged() {
4907             mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
4908                     .ignoreProximitySensorUntilChanged();
4909         }
4910 
4911         @Override
getRefreshRateSwitchingType()4912         public int getRefreshRateSwitchingType() {
4913             return getRefreshRateSwitchingTypeInternal();
4914         }
4915 
4916         @Override
getRefreshRateForDisplayAndSensor(int displayId, String sensorName, String sensorType)4917         public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName,
4918                 String sensorType) {
4919             final SensorManager sensorManager;
4920             synchronized (mSyncRoot) {
4921                 sensorManager = mSensorManager;
4922             }
4923             if (sensorManager == null) {
4924                 return null;
4925             }
4926 
4927             // Verify that the specified sensor exists.
4928             final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName,
4929                     SensorUtils.NO_FALLBACK);
4930             if (sensor == null) {
4931                 return null;
4932             }
4933 
4934             synchronized (mSyncRoot) {
4935                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
4936                 if (display == null) {
4937                     return null;
4938                 }
4939                 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
4940                 if (device == null) {
4941                     return null;
4942                 }
4943                 final DisplayDeviceConfig config = device.getDisplayDeviceConfig();
4944                 SensorData sensorData = config.getProximitySensor();
4945                 if (sensorData != null && sensorData.matches(sensorName, sensorType)) {
4946                     return new RefreshRateRange(sensorData.minRefreshRate,
4947                             sensorData.maxRefreshRate);
4948                 }
4949             }
4950             return null;
4951         }
4952 
4953         @Override
getRefreshRateLimitations(int displayId)4954         public List<RefreshRateLimitation> getRefreshRateLimitations(int displayId) {
4955             final DisplayDeviceConfig config;
4956             synchronized (mSyncRoot) {
4957                 final DisplayDevice device = getDeviceForDisplayLocked(displayId);
4958                 if (device == null) {
4959                     return null;
4960                 }
4961                 config = device.getDisplayDeviceConfig();
4962             }
4963             return config.getRefreshRateLimitations();
4964         }
4965 
4966         @Override
setWindowManagerMirroring(int displayId, boolean isMirroring)4967         public void setWindowManagerMirroring(int displayId, boolean isMirroring) {
4968             synchronized (mSyncRoot) {
4969                 final DisplayDevice device = getDeviceForDisplayLocked(displayId);
4970                 if (device != null) {
4971                     device.setWindowManagerMirroringLocked(isMirroring);
4972                 }
4973             }
4974         }
4975 
4976         @Override
getDisplaySurfaceDefaultSize(int displayId)4977         public Point getDisplaySurfaceDefaultSize(int displayId) {
4978             final DisplayDevice device;
4979             synchronized (mSyncRoot) {
4980                 device = getDeviceForDisplayLocked(displayId);
4981                 if (device == null) {
4982                     return null;
4983                 }
4984                 return device.getDisplaySurfaceDefaultSizeLocked();
4985             }
4986         }
4987 
4988         @Override
onEarlyInteractivityChange(boolean interactive)4989         public void onEarlyInteractivityChange(boolean interactive) {
4990             mLogicalDisplayMapper.onEarlyInteractivityChange(interactive);
4991         }
4992 
4993         @Override
getDisplayWindowPolicyController(int displayId)4994         public DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId) {
4995             synchronized (mSyncRoot) {
4996                 if (mDisplayWindowPolicyControllers.contains(displayId)) {
4997                     return mDisplayWindowPolicyControllers.get(displayId).second;
4998                 }
4999                 return null;
5000             }
5001         }
5002 
5003         @Override
getDisplayIdToMirror(int displayId)5004         public int getDisplayIdToMirror(int displayId) {
5005             synchronized (mSyncRoot) {
5006                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
5007                 if (display == null) {
5008                     return Display.INVALID_DISPLAY;
5009                 }
5010 
5011                 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
5012                 final boolean isRearDisplay = display.getDevicePositionLocked() == POSITION_REAR;
5013                 final boolean ownContent = ((displayDevice.getDisplayDeviceInfoLocked().flags
5014                         & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0) || isRearDisplay;
5015                 // If the display has enabled mirroring, but specified that it will be managed by
5016                 // WindowManager, return an invalid display id. This is to ensure we don't
5017                 // accidentally select the display id to mirror based on DM logic and instead allow
5018                 // the caller to specify what area to mirror.
5019                 if (ownContent || displayDevice.isWindowManagerMirroringLocked()) {
5020                     return Display.INVALID_DISPLAY;
5021                 }
5022 
5023                 int displayIdToMirror = displayDevice.getDisplayIdToMirrorLocked();
5024                 LogicalDisplay displayToMirror = mLogicalDisplayMapper.getDisplayLocked(
5025                         displayIdToMirror);
5026                 // If the displayId for the requested mirror doesn't exist, fallback to mirroring
5027                 // default display.
5028                 if (displayToMirror == null) {
5029                     displayIdToMirror = Display.DEFAULT_DISPLAY;
5030                 }
5031                 return displayIdToMirror;
5032             }
5033         }
5034 
5035         @Override
getDisplayNativePrimaries(int displayId)5036         public SurfaceControl.DisplayPrimaries getDisplayNativePrimaries(int displayId) {
5037             IBinder displayToken;
5038             synchronized (mSyncRoot) {
5039                 displayToken = getDisplayToken(displayId);
5040                 if (displayToken == null) {
5041                     throw new IllegalArgumentException("Invalid displayId=" + displayId);
5042                 }
5043             }
5044 
5045             return SurfaceControl.getDisplayNativePrimaries(displayToken);
5046         }
5047 
5048         @Override
getHostUsiVersion(int displayId)5049         public HostUsiVersion getHostUsiVersion(int displayId) {
5050             synchronized (mSyncRoot) {
5051                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
5052                 if (display == null) {
5053                     return null;
5054                 }
5055 
5056                 return display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig()
5057                         .getHostUsiVersion();
5058             }
5059         }
5060 
5061         @Override
getAmbientLightSensorData(int displayId)5062         public AmbientLightSensorData getAmbientLightSensorData(int displayId) {
5063             synchronized (mSyncRoot) {
5064                 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
5065                 if (display == null) {
5066                     return null;
5067                 }
5068                 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
5069                 if (device == null) {
5070                     return null;
5071                 }
5072                 SensorData data = device.getDisplayDeviceConfig().getAmbientLightSensor();
5073                 return new AmbientLightSensorData(data.name, data.type);
5074             }
5075         }
5076 
5077         @Override
getDisplayGroupIds()5078         public IntArray getDisplayGroupIds() {
5079             Set<Integer> visitedIds = new ArraySet<>();
5080             IntArray displayGroupIds = new IntArray();
5081             synchronized (mSyncRoot) {
5082                 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
5083                     int groupId = mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
5084                             logicalDisplay.getDisplayIdLocked());
5085                     if (!visitedIds.contains(groupId)) {
5086                         visitedIds.add(groupId);
5087                         displayGroupIds.add(groupId);
5088                     }
5089                 });
5090             }
5091             return displayGroupIds;
5092         }
5093 
5094         @Override
registerDisplayOffloader( int displayId, @NonNull DisplayManagerInternal.DisplayOffloader displayOffloader)5095         public DisplayManagerInternal.DisplayOffloadSession registerDisplayOffloader(
5096                 int displayId, @NonNull DisplayManagerInternal.DisplayOffloader displayOffloader) {
5097             if (!mFlags.isDisplayOffloadEnabled()) {
5098                 return null;
5099             }
5100             synchronized (mSyncRoot) {
5101                 LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
5102                 if (logicalDisplay == null) {
5103                     Slog.w(TAG, "registering DisplayOffloader: LogicalDisplay for displayId="
5104                             + displayId + " is not found. No Op.");
5105                     return null;
5106                 }
5107 
5108                 DisplayPowerControllerInterface displayPowerController =
5109                         mDisplayPowerControllers.get(logicalDisplay.getDisplayIdLocked());
5110                 if (displayPowerController == null) {
5111                     Slog.w(TAG,
5112                             "setting doze state override: DisplayPowerController for displayId="
5113                                     + displayId + " is unavailable. No Op.");
5114                     return null;
5115                 }
5116 
5117                 DisplayOffloadSessionImpl session = new DisplayOffloadSessionImpl(displayOffloader,
5118                         displayPowerController);
5119                 logicalDisplay.setDisplayOffloadSessionLocked(session);
5120                 displayPowerController.setDisplayOffloadSession(session);
5121                 return session;
5122             }
5123         }
5124 
5125         @Override
onPresentation(int displayId, boolean isShown)5126         public void onPresentation(int displayId, boolean isShown) {
5127             mExternalDisplayPolicy.onPresentation(displayId, isShown);
5128         }
5129     }
5130 
5131     class DesiredDisplayModeSpecsObserver
5132             implements DisplayModeDirector.DesiredDisplayModeSpecsListener {
5133 
5134         private final Consumer<LogicalDisplay> mSpecsChangedConsumer = display -> {
5135             int displayId = display.getDisplayIdLocked();
5136             DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
5137                     mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId);
5138             DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs =
5139                     display.getDesiredDisplayModeSpecsLocked();
5140             if (DEBUG) {
5141                 Slog.i(TAG,
5142                         "Comparing display specs: " + desiredDisplayModeSpecs
5143                                 + ", existing: " + existingDesiredDisplayModeSpecs);
5144             }
5145             if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) {
5146                 display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs);
5147                 mChanged = true;
5148             }
5149         };
5150 
5151         @GuardedBy("mSyncRoot")
5152         private boolean mChanged = false;
5153 
onDesiredDisplayModeSpecsChanged()5154         public void onDesiredDisplayModeSpecsChanged() {
5155             synchronized (mSyncRoot) {
5156                 mChanged = false;
5157                 mLogicalDisplayMapper.forEachLocked(mSpecsChangedConsumer,
5158                         /* includeDisabled= */ false);
5159                 if (mChanged) {
5160                     scheduleTraversalLocked(false);
5161                     mChanged = false;
5162                 }
5163             }
5164         }
5165     }
5166 
5167     /**
5168      * Listens to changes in device state and reports the state to LogicalDisplayMapper.
5169      */
5170     class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
5171 
5172         @Override
onDeviceStateChanged(DeviceState deviceState)5173         public void onDeviceStateChanged(DeviceState deviceState) {
5174             synchronized (mSyncRoot) {
5175                 // Notify WindowManager that we are about to handle new device state, this should
5176                 // be sent before any work related to the device state in DisplayManager, so
5177                 // WindowManager could do implement that depends on the device state and display
5178                 // changes (serializes device state update and display change events)
5179                 Message msg = mHandler.obtainMessage(MSG_RECEIVED_DEVICE_STATE);
5180                 msg.arg1 = deviceState.getIdentifier();
5181                 mHandler.sendMessage(msg);
5182 
5183                 mLogicalDisplayMapper
5184                         .setDeviceStateLocked(deviceState.getIdentifier());
5185             }
5186         }
5187     };
5188 
5189     private static class BrightnessPair {
5190         public float brightness;
5191         public float sdrBrightness;
5192 
BrightnessPair(float brightness, float sdrBrightness)5193         BrightnessPair(float brightness, float sdrBrightness) {
5194             this.brightness = brightness;
5195             this.sdrBrightness = sdrBrightness;
5196         }
5197     }
5198 
5199     /**
5200      * Functional interface for providing time.
5201      * TODO(b/184781936): merge with PowerManagerService.Clock
5202      */
5203     @VisibleForTesting
5204     public interface Clock {
5205         /**
5206          * Returns current time in milliseconds since boot, not counting time spent in deep sleep.
5207          */
uptimeMillis()5208         long uptimeMillis();
5209     }
5210 
5211     /**
5212      * Implements necessary functionality for {@link ExternalDisplayPolicy}
5213      */
5214     private class ExternalDisplayPolicyInjector implements ExternalDisplayPolicy.Injector {
5215         /**
5216          * Sends event for the display.
5217          */
5218         @Override
sendExternalDisplayEventLocked(@onNull final LogicalDisplay display, @DisplayEvent int event)5219         public void sendExternalDisplayEventLocked(@NonNull final LogicalDisplay display,
5220                 @DisplayEvent int event) {
5221             sendDisplayEventLocked(display, event);
5222         }
5223 
5224         /**
5225          * Gets thermal service
5226          */
5227         @Override
5228         @Nullable
getThermalService()5229         public IThermalService getThermalService() {
5230             return IThermalService.Stub.asInterface(ServiceManager.getService(
5231                     Context.THERMAL_SERVICE));
5232         }
5233 
5234         /**
5235          * @return display manager flags.
5236          */
5237         @Override
5238         @NonNull
getFlags()5239         public DisplayManagerFlags getFlags() {
5240             return mFlags;
5241         }
5242 
5243         /**
5244          * @return Logical display mapper.
5245          */
5246         @Override
5247         @NonNull
getLogicalDisplayMapper()5248         public LogicalDisplayMapper getLogicalDisplayMapper() {
5249             return mLogicalDisplayMapper;
5250         }
5251 
5252         /**
5253          * @return Sync root, for synchronization on this object across display manager.
5254          */
5255         @Override
5256         @NonNull
getSyncRoot()5257         public SyncRoot getSyncRoot() {
5258             return mSyncRoot;
5259         }
5260 
5261         /**
5262          * Notification manager for display manager
5263          */
5264         @Override
5265         @NonNull
getDisplayNotificationManager()5266         public DisplayNotificationManager getDisplayNotificationManager() {
5267             return mDisplayNotificationManager;
5268         }
5269 
5270         /**
5271          * Handler to use for notification sending to avoid requiring POST_NOTIFICATION permission.
5272          */
5273         @Override
5274         @NonNull
getHandler()5275         public Handler getHandler() {
5276             return mHandler;
5277         }
5278 
5279         /**
5280          * Gets service used for metrics collection.
5281          */
5282         @Override
5283         @NonNull
getExternalDisplayStatsService()5284         public ExternalDisplayStatsService getExternalDisplayStatsService() {
5285             return mExternalDisplayStatsService;
5286         }
5287     }
5288 }
5289