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