• 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.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
20 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
22 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
23 import static android.hardware.display.DisplayManager
24         .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.internal.util.DumpUtils;
28 import com.android.internal.util.IndentingPrintWriter;
29 
30 import android.Manifest;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.UserIdInt;
34 import android.app.AppOpsManager;
35 import android.content.Context;
36 import android.content.pm.PackageManager;
37 import android.content.pm.ParceledListSlice;
38 import android.content.res.Resources;
39 import android.content.res.TypedArray;
40 import android.graphics.Point;
41 import android.hardware.SensorManager;
42 import android.hardware.display.AmbientBrightnessDayStats;
43 import android.hardware.display.BrightnessChangeEvent;
44 import android.hardware.display.BrightnessConfiguration;
45 import android.hardware.display.Curve;
46 import android.hardware.display.DisplayManagerGlobal;
47 import android.hardware.display.DisplayManagerInternal;
48 import android.hardware.display.DisplayViewport;
49 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
50 import android.hardware.display.IDisplayManager;
51 import android.hardware.display.IDisplayManagerCallback;
52 import android.hardware.display.IVirtualDisplayCallback;
53 import android.hardware.display.WifiDisplayStatus;
54 import android.hardware.input.InputManagerInternal;
55 import android.media.projection.IMediaProjection;
56 import android.media.projection.IMediaProjectionManager;
57 import android.os.Binder;
58 import android.os.Handler;
59 import android.os.IBinder;
60 import android.os.IBinder.DeathRecipient;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.os.PowerManager;
64 import android.os.Process;
65 import android.os.RemoteException;
66 import android.os.ResultReceiver;
67 import android.os.ServiceManager;
68 import android.os.ShellCallback;
69 import android.os.SystemClock;
70 import android.os.SystemProperties;
71 import android.os.Trace;
72 import android.os.UserHandle;
73 import android.os.UserManager;
74 import android.provider.Settings;
75 import android.text.TextUtils;
76 import android.util.IntArray;
77 import android.util.Pair;
78 import android.util.Slog;
79 import android.util.SparseArray;
80 import android.util.Spline;
81 import android.view.Display;
82 import android.view.DisplayInfo;
83 import android.view.Surface;
84 import android.view.SurfaceControl;
85 
86 import com.android.internal.util.Preconditions;
87 import com.android.server.AnimationThread;
88 import com.android.server.DisplayThread;
89 import com.android.server.LocalServices;
90 import com.android.server.SystemService;
91 import com.android.server.UiThread;
92 import com.android.server.wm.WindowManagerInternal;
93 import com.android.server.wm.SurfaceAnimationThread;
94 
95 import java.io.FileDescriptor;
96 import java.io.PrintWriter;
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.List;
100 import java.util.concurrent.CopyOnWriteArrayList;
101 
102 /**
103  * Manages attached displays.
104  * <p>
105  * The {@link DisplayManagerService} manages the global lifecycle of displays,
106  * decides how to configure logical displays based on the physical display devices currently
107  * attached, sends notifications to the system and to applications when the state
108  * changes, and so on.
109  * </p><p>
110  * The display manager service relies on a collection of {@link DisplayAdapter} components,
111  * for discovering and configuring physical display devices attached to the system.
112  * There are separate display adapters for each manner that devices are attached:
113  * one display adapter for built-in local displays, one for simulated non-functional
114  * displays when the system is headless, one for simulated overlay displays used for
115  * development, one for wifi displays, etc.
116  * </p><p>
117  * Display adapters are only weakly coupled to the display manager service.
118  * Display adapters communicate changes in display device state to the display manager
119  * service asynchronously via a {@link DisplayAdapter.Listener} registered
120  * by the display manager service.  This separation of concerns is important for
121  * two main reasons.  First, it neatly encapsulates the responsibilities of these
122  * two classes: display adapters handle individual display devices whereas
123  * the display manager service handles the global state.  Second, it eliminates
124  * the potential for deadlocks resulting from asynchronous display device discovery.
125  * </p>
126  *
127  * <h3>Synchronization</h3>
128  * <p>
129  * Because the display manager may be accessed by multiple threads, the synchronization
130  * story gets a little complicated.  In particular, the window manager may call into
131  * the display manager while holding a surface transaction with the expectation that
132  * it can apply changes immediately.  Unfortunately, that means we can't just do
133  * everything asynchronously (*grump*).
134  * </p><p>
135  * To make this work, all of the objects that belong to the display manager must
136  * use the same lock.  We call this lock the synchronization root and it has a unique
137  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
138  * named with the "Locked" suffix.
139  * </p><p>
140  * Where things get tricky is that the display manager is not allowed to make
141  * any potentially reentrant calls, especially into the window manager.  We generally
142  * avoid this by making all potentially reentrant out-calls asynchronous.
143  * </p>
144  */
145 public final class DisplayManagerService extends SystemService {
146     private static final String TAG = "DisplayManagerService";
147     private static final boolean DEBUG = false;
148 
149     // When this system property is set to 0, WFD is forcibly disabled on boot.
150     // When this system property is set to 1, WFD is forcibly enabled on boot.
151     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
152     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
153 
154     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
155 
156     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
157     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
158     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
159     private static final int MSG_REQUEST_TRAVERSAL = 4;
160     private static final int MSG_UPDATE_VIEWPORT = 5;
161     private static final int MSG_REGISTER_BRIGHTNESS_TRACKER = 6;
162     private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 7;
163 
164     private final Context mContext;
165     private final DisplayManagerHandler mHandler;
166     private final Handler mUiHandler;
167     private final DisplayAdapterListener mDisplayAdapterListener;
168     private WindowManagerInternal mWindowManagerInternal;
169     private InputManagerInternal mInputManagerInternal;
170     private IMediaProjectionManager mProjectionService;
171 
172     // The synchronization root for the display manager.
173     // This lock guards most of the display manager's state.
174     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
175     // into WindowManagerService methods that require mWindowMap while holding this unless you are
176     // very very sure that no deadlock can occur.
177     private final SyncRoot mSyncRoot = new SyncRoot();
178 
179     // True if in safe mode.
180     // This option may disable certain display adapters.
181     public boolean mSafeMode;
182 
183     // True if we are in a special boot mode where only core applications and
184     // services should be started.  This option may disable certain display adapters.
185     public boolean mOnlyCore;
186 
187     // True if the display manager service should pretend there is only one display
188     // and only tell applications about the existence of the default logical display.
189     // The display manager can still mirror content to secondary displays but applications
190     // cannot present unique content on those displays.
191     // Used for demonstration purposes only.
192     private final boolean mSingleDisplayDemoMode;
193 
194     // All callback records indexed by calling process id.
195     public final SparseArray<CallbackRecord> mCallbacks =
196             new SparseArray<CallbackRecord>();
197 
198     // List of all currently registered display adapters.
199     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
200 
201     // List of all currently connected display devices.
202     private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
203 
204     // List of all logical displays indexed by logical display id.
205     private final SparseArray<LogicalDisplay> mLogicalDisplays =
206             new SparseArray<LogicalDisplay>();
207     private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
208 
209     // List of all display transaction listeners.
210     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
211             new CopyOnWriteArrayList<DisplayTransactionListener>();
212 
213     // Display power controller.
214     private DisplayPowerController mDisplayPowerController;
215 
216     // The overall display state, independent of changes that might influence one
217     // display or another in particular.
218     private int mGlobalDisplayState = Display.STATE_ON;
219 
220     // The overall display brightness.
221     // For now, this only applies to the built-in display but we may split it up eventually.
222     private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
223 
224     // Set to true when there are pending display changes that have yet to be applied
225     // to the surface flinger state.
226     private boolean mPendingTraversal;
227 
228     // The Wifi display adapter, or null if not registered.
229     private WifiDisplayAdapter mWifiDisplayAdapter;
230 
231     // The number of active wifi display scan requests.
232     private int mWifiDisplayScanRequestCount;
233 
234     // The virtual display adapter, or null if not registered.
235     private VirtualDisplayAdapter mVirtualDisplayAdapter;
236 
237     // The User ID of the current user
238     private @UserIdInt int mCurrentUserId;
239 
240     // The stable device screen height and width. These are not tied to a specific display, even
241     // the default display, because they need to be stable over the course of the device's entire
242     // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
243     // device).
244     private Point mStableDisplaySize = new Point();
245 
246     // Viewports of the default display and the display that should receive touch
247     // input from an external source.  Used by the input system.
248     private final DisplayViewport mDefaultViewport = new DisplayViewport();
249     private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
250     private final ArrayList<DisplayViewport> mVirtualTouchViewports = new ArrayList<>();
251 
252     // Persistent data store for all internal settings maintained by the display manager service.
253     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
254 
255     // Temporary callback list, used when sending display events to applications.
256     // May be used outside of the lock but only on the handler thread.
257     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
258 
259     // Temporary display info, used for comparing display configurations.
260     private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
261 
262     // Temporary viewports, used when sending new viewport information to the
263     // input system.  May be used outside of the lock but only on the handler thread.
264     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
265     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
266     private final ArrayList<DisplayViewport> mTempVirtualTouchViewports = new ArrayList<>();
267 
268     // The default color mode for default displays. Overrides the usual
269     // Display.Display.COLOR_MODE_DEFAULT for displays with the
270     // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
271     private final int mDefaultDisplayDefaultColorMode;
272 
273     // Temporary list of deferred work to perform when setting the display state.
274     // Only used by requestDisplayState.  The field is self-synchronized and only
275     // intended for use inside of the requestGlobalDisplayStateInternal function.
276     private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
277 
278     // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
279     private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
280 
281     private final Injector mInjector;
282 
283     // The minimum brightness curve, which guarantess that any brightness curve that dips below it
284     // is rejected by the system.
285     private final Curve mMinimumBrightnessCurve;
286     private final Spline mMinimumBrightnessSpline;
287 
DisplayManagerService(Context context)288     public DisplayManagerService(Context context) {
289         this(context, new Injector());
290     }
291 
292     @VisibleForTesting
DisplayManagerService(Context context, Injector injector)293     DisplayManagerService(Context context, Injector injector) {
294         super(context);
295         mInjector = injector;
296         mContext = context;
297         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
298         mUiHandler = UiThread.getHandler();
299         mDisplayAdapterListener = new DisplayAdapterListener();
300         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
301         Resources resources = mContext.getResources();
302         mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
303                 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
304         float[] lux = getFloatArray(resources.obtainTypedArray(
305                 com.android.internal.R.array.config_minimumBrightnessCurveLux));
306         float[] nits = getFloatArray(resources.obtainTypedArray(
307                 com.android.internal.R.array.config_minimumBrightnessCurveNits));
308         mMinimumBrightnessCurve = new Curve(lux, nits);
309         mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
310 
311         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
312         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
313         mCurrentUserId = UserHandle.USER_SYSTEM;
314     }
315 
setupSchedulerPolicies()316     public void setupSchedulerPolicies() {
317         // android.display and android.anim is critical to user experience and we should make sure
318         // it is not in the default foregroup groups, add it to top-app to make sure it uses all
319         // the cores and scheduling settings for top-app when it runs.
320         Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
321                 Process.THREAD_GROUP_TOP_APP);
322         Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
323                 Process.THREAD_GROUP_TOP_APP);
324         Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
325                 Process.THREAD_GROUP_TOP_APP);
326     }
327 
328     @Override
onStart()329     public void onStart() {
330         // We need to pre-load the persistent data store so it's ready before the default display
331         // adapter is up so that we have it's configuration. We could load it lazily, but since
332         // we're going to have to read it in eventually we may as well do it here rather than after
333         // we've waited for the display to register itself with us.
334 		synchronized(mSyncRoot) {
335 			mPersistentDataStore.loadIfNeeded();
336 			loadStableDisplayValuesLocked();
337         }
338         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
339 
340         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
341                 true /*allowIsolated*/);
342         publishLocalService(DisplayManagerInternal.class, new LocalService());
343         publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
344     }
345 
346     @Override
onBootPhase(int phase)347     public void onBootPhase(int phase) {
348         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
349             synchronized (mSyncRoot) {
350                 long timeout = SystemClock.uptimeMillis()
351                         + mInjector.getDefaultDisplayDelayTimeout();
352                 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
353                         mVirtualDisplayAdapter == null) {
354                     long delay = timeout - SystemClock.uptimeMillis();
355                     if (delay <= 0) {
356                         throw new RuntimeException("Timeout waiting for default display "
357                                 + "to be initialized. DefaultDisplay="
358                                 + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
359                                 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
360                     }
361                     if (DEBUG) {
362                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
363                     }
364                     try {
365                         mSyncRoot.wait(delay);
366                     } catch (InterruptedException ex) {
367                     }
368                 }
369             }
370         }
371     }
372 
373     @Override
onSwitchUser(@serIdInt int newUserId)374     public void onSwitchUser(@UserIdInt int newUserId) {
375         final int userSerial = getUserManager().getUserSerialNumber(newUserId);
376         synchronized (mSyncRoot) {
377             if (mCurrentUserId != newUserId) {
378                 mCurrentUserId = newUserId;
379                 BrightnessConfiguration config =
380                         mPersistentDataStore.getBrightnessConfiguration(userSerial);
381                 mDisplayPowerController.setBrightnessConfiguration(config);
382             }
383             mDisplayPowerController.onSwitchUser(newUserId);
384         }
385     }
386 
387     // TODO: Use dependencies or a boot phase
windowManagerAndInputReady()388     public void windowManagerAndInputReady() {
389         synchronized (mSyncRoot) {
390             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
391             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
392             scheduleTraversalLocked(false);
393         }
394     }
395 
396     /**
397      * Called when the system is ready to go.
398      */
systemReady(boolean safeMode, boolean onlyCore)399     public void systemReady(boolean safeMode, boolean onlyCore) {
400         synchronized (mSyncRoot) {
401             mSafeMode = safeMode;
402             mOnlyCore = onlyCore;
403         }
404 
405         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
406         mHandler.sendEmptyMessage(MSG_REGISTER_BRIGHTNESS_TRACKER);
407     }
408 
409     @VisibleForTesting
getDisplayHandler()410     Handler getDisplayHandler() {
411         return mHandler;
412     }
413 
loadStableDisplayValuesLocked()414     private void loadStableDisplayValuesLocked() {
415         final Point size = mPersistentDataStore.getStableDisplaySize();
416         if (size.x > 0 && size.y > 0) {
417             // Just set these values directly so we don't write the display persistent data again
418             // unnecessarily
419             mStableDisplaySize.set(size.x, size.y);
420         } else {
421             final Resources res = mContext.getResources();
422             final int width = res.getInteger(
423                     com.android.internal.R.integer.config_stableDeviceDisplayWidth);
424             final int height = res.getInteger(
425                     com.android.internal.R.integer.config_stableDeviceDisplayHeight);
426             if (width > 0 && height > 0) {
427                 setStableDisplaySizeLocked(width, height);
428             }
429         }
430     }
431 
getStableDisplaySizeInternal()432     private Point getStableDisplaySizeInternal() {
433         Point r = new Point();
434         synchronized (mSyncRoot) {
435             if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
436                 r.set(mStableDisplaySize.x, mStableDisplaySize.y);
437             }
438         }
439         return r;
440     }
441 
registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)442     private void registerDisplayTransactionListenerInternal(
443             DisplayTransactionListener listener) {
444         // List is self-synchronized copy-on-write.
445         mDisplayTransactionListeners.add(listener);
446     }
447 
unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)448     private void unregisterDisplayTransactionListenerInternal(
449             DisplayTransactionListener listener) {
450         // List is self-synchronized copy-on-write.
451         mDisplayTransactionListeners.remove(listener);
452     }
453 
setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info)454     private void setDisplayInfoOverrideFromWindowManagerInternal(
455             int displayId, DisplayInfo info) {
456         synchronized (mSyncRoot) {
457             LogicalDisplay display = mLogicalDisplays.get(displayId);
458             if (display != null) {
459                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
460                     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
461                     scheduleTraversalLocked(false);
462                 }
463             }
464         }
465     }
466 
467     /**
468      * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
469      */
getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)470     private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
471         synchronized (mSyncRoot) {
472             final LogicalDisplay display = mLogicalDisplays.get(displayId);
473             if (display != null) {
474                 display.getNonOverrideDisplayInfoLocked(outInfo);
475             }
476         }
477     }
478 
479     @VisibleForTesting
performTraversalInternal(SurfaceControl.Transaction t)480     void performTraversalInternal(SurfaceControl.Transaction t) {
481         synchronized (mSyncRoot) {
482             if (!mPendingTraversal) {
483                 return;
484             }
485             mPendingTraversal = false;
486 
487             performTraversalLocked(t);
488         }
489 
490         // List is self-synchronized copy-on-write.
491         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
492             listener.onDisplayTransaction();
493         }
494     }
495 
requestGlobalDisplayStateInternal(int state, int brightness)496     private void requestGlobalDisplayStateInternal(int state, int brightness) {
497         if (state == Display.STATE_UNKNOWN) {
498             state = Display.STATE_ON;
499         }
500         if (state == Display.STATE_OFF) {
501             brightness = PowerManager.BRIGHTNESS_OFF;
502         } else if (brightness < 0) {
503             brightness = PowerManager.BRIGHTNESS_DEFAULT;
504         } else if (brightness > PowerManager.BRIGHTNESS_ON) {
505             brightness = PowerManager.BRIGHTNESS_ON;
506         }
507 
508         synchronized (mTempDisplayStateWorkQueue) {
509             try {
510                 // Update the display state within the lock.
511                 // Note that we do not need to schedule traversals here although it
512                 // may happen as a side-effect of displays changing state.
513                 synchronized (mSyncRoot) {
514                     if (mGlobalDisplayState == state
515                             && mGlobalDisplayBrightness == brightness) {
516                         return; // no change
517                     }
518 
519                     Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
520                             + Display.stateToString(state)
521                             + ", brightness=" + brightness + ")");
522                     mGlobalDisplayState = state;
523                     mGlobalDisplayBrightness = brightness;
524                     applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
525                 }
526 
527                 // Setting the display power state can take hundreds of milliseconds
528                 // to complete so we defer the most expensive part of the work until
529                 // after we have exited the critical section to avoid blocking other
530                 // threads for a long time.
531                 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
532                     mTempDisplayStateWorkQueue.get(i).run();
533                 }
534                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
535             } finally {
536                 mTempDisplayStateWorkQueue.clear();
537             }
538         }
539     }
540 
getDisplayInfoInternal(int displayId, int callingUid)541     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
542         synchronized (mSyncRoot) {
543             LogicalDisplay display = mLogicalDisplays.get(displayId);
544             if (display != null) {
545                 DisplayInfo info = display.getDisplayInfoLocked();
546                 if (info.hasAccess(callingUid)
547                         || isUidPresentOnDisplayInternal(callingUid, displayId)) {
548                     return info;
549                 }
550             }
551             return null;
552         }
553     }
554 
getDisplayIdsInternal(int callingUid)555     private int[] getDisplayIdsInternal(int callingUid) {
556         synchronized (mSyncRoot) {
557             final int count = mLogicalDisplays.size();
558             int[] displayIds = new int[count];
559             int n = 0;
560             for (int i = 0; i < count; i++) {
561                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
562                 DisplayInfo info = display.getDisplayInfoLocked();
563                 if (info.hasAccess(callingUid)) {
564                     displayIds[n++] = mLogicalDisplays.keyAt(i);
565                 }
566             }
567             if (n != count) {
568                 displayIds = Arrays.copyOfRange(displayIds, 0, n);
569             }
570             return displayIds;
571         }
572     }
573 
registerCallbackInternal(IDisplayManagerCallback callback, int callingPid)574     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
575         synchronized (mSyncRoot) {
576             if (mCallbacks.get(callingPid) != null) {
577                 throw new SecurityException("The calling process has already "
578                         + "registered an IDisplayManagerCallback.");
579             }
580 
581             CallbackRecord record = new CallbackRecord(callingPid, callback);
582             try {
583                 IBinder binder = callback.asBinder();
584                 binder.linkToDeath(record, 0);
585             } catch (RemoteException ex) {
586                 // give up
587                 throw new RuntimeException(ex);
588             }
589 
590             mCallbacks.put(callingPid, record);
591         }
592     }
593 
onCallbackDied(CallbackRecord record)594     private void onCallbackDied(CallbackRecord record) {
595         synchronized (mSyncRoot) {
596             mCallbacks.remove(record.mPid);
597             stopWifiDisplayScanLocked(record);
598         }
599     }
600 
startWifiDisplayScanInternal(int callingPid)601     private void startWifiDisplayScanInternal(int callingPid) {
602         synchronized (mSyncRoot) {
603             CallbackRecord record = mCallbacks.get(callingPid);
604             if (record == null) {
605                 throw new IllegalStateException("The calling process has not "
606                         + "registered an IDisplayManagerCallback.");
607             }
608             startWifiDisplayScanLocked(record);
609         }
610     }
611 
startWifiDisplayScanLocked(CallbackRecord record)612     private void startWifiDisplayScanLocked(CallbackRecord record) {
613         if (!record.mWifiDisplayScanRequested) {
614             record.mWifiDisplayScanRequested = true;
615             if (mWifiDisplayScanRequestCount++ == 0) {
616                 if (mWifiDisplayAdapter != null) {
617                     mWifiDisplayAdapter.requestStartScanLocked();
618                 }
619             }
620         }
621     }
622 
stopWifiDisplayScanInternal(int callingPid)623     private void stopWifiDisplayScanInternal(int callingPid) {
624         synchronized (mSyncRoot) {
625             CallbackRecord record = mCallbacks.get(callingPid);
626             if (record == null) {
627                 throw new IllegalStateException("The calling process has not "
628                         + "registered an IDisplayManagerCallback.");
629             }
630             stopWifiDisplayScanLocked(record);
631         }
632     }
633 
stopWifiDisplayScanLocked(CallbackRecord record)634     private void stopWifiDisplayScanLocked(CallbackRecord record) {
635         if (record.mWifiDisplayScanRequested) {
636             record.mWifiDisplayScanRequested = false;
637             if (--mWifiDisplayScanRequestCount == 0) {
638                 if (mWifiDisplayAdapter != null) {
639                     mWifiDisplayAdapter.requestStopScanLocked();
640                 }
641             } else if (mWifiDisplayScanRequestCount < 0) {
642                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
643                         + mWifiDisplayScanRequestCount);
644                 mWifiDisplayScanRequestCount = 0;
645             }
646         }
647     }
648 
connectWifiDisplayInternal(String address)649     private void connectWifiDisplayInternal(String address) {
650         synchronized (mSyncRoot) {
651             if (mWifiDisplayAdapter != null) {
652                 mWifiDisplayAdapter.requestConnectLocked(address);
653             }
654         }
655     }
656 
pauseWifiDisplayInternal()657     private void pauseWifiDisplayInternal() {
658         synchronized (mSyncRoot) {
659             if (mWifiDisplayAdapter != null) {
660                 mWifiDisplayAdapter.requestPauseLocked();
661             }
662         }
663     }
664 
resumeWifiDisplayInternal()665     private void resumeWifiDisplayInternal() {
666         synchronized (mSyncRoot) {
667             if (mWifiDisplayAdapter != null) {
668                 mWifiDisplayAdapter.requestResumeLocked();
669             }
670         }
671     }
672 
disconnectWifiDisplayInternal()673     private void disconnectWifiDisplayInternal() {
674         synchronized (mSyncRoot) {
675             if (mWifiDisplayAdapter != null) {
676                 mWifiDisplayAdapter.requestDisconnectLocked();
677             }
678         }
679     }
680 
renameWifiDisplayInternal(String address, String alias)681     private void renameWifiDisplayInternal(String address, String alias) {
682         synchronized (mSyncRoot) {
683             if (mWifiDisplayAdapter != null) {
684                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
685             }
686         }
687     }
688 
forgetWifiDisplayInternal(String address)689     private void forgetWifiDisplayInternal(String address) {
690         synchronized (mSyncRoot) {
691             if (mWifiDisplayAdapter != null) {
692                 mWifiDisplayAdapter.requestForgetLocked(address);
693             }
694         }
695     }
696 
getWifiDisplayStatusInternal()697     private WifiDisplayStatus getWifiDisplayStatusInternal() {
698         synchronized (mSyncRoot) {
699             if (mWifiDisplayAdapter != null) {
700                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
701             }
702             return new WifiDisplayStatus();
703         }
704     }
705 
requestColorModeInternal(int displayId, int colorMode)706     private void requestColorModeInternal(int displayId, int colorMode) {
707         synchronized (mSyncRoot) {
708             LogicalDisplay display = mLogicalDisplays.get(displayId);
709             if (display != null &&
710                     display.getRequestedColorModeLocked() != colorMode) {
711                 display.setRequestedColorModeLocked(colorMode);
712                 scheduleTraversalLocked(false);
713             }
714         }
715     }
716 
setSaturationLevelInternal(float level)717     private void setSaturationLevelInternal(float level) {
718         if (level < 0 || level > 1) {
719             throw new IllegalArgumentException("Saturation level must be between 0 and 1");
720         }
721         float[] matrix = (level == 1.0f ? null : computeSaturationMatrix(level));
722         DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
723         dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION, matrix);
724     }
725 
computeSaturationMatrix(float saturation)726     private static float[] computeSaturationMatrix(float saturation) {
727         float desaturation = 1.0f - saturation;
728         float[] luminance = {0.231f * desaturation, 0.715f * desaturation, 0.072f * desaturation};
729         float[] matrix = {
730             luminance[0] + saturation, luminance[0], luminance[0], 0,
731             luminance[1], luminance[1] + saturation, luminance[1], 0,
732             luminance[2], luminance[2], luminance[2] + saturation, 0,
733             0, 0, 0, 1
734         };
735         return matrix;
736     }
737 
createVirtualDisplayInternal(IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags, String uniqueId)738     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
739             IMediaProjection projection, int callingUid, String packageName, String name, int width,
740             int height, int densityDpi, Surface surface, int flags, String uniqueId) {
741         synchronized (mSyncRoot) {
742             if (mVirtualDisplayAdapter == null) {
743                 Slog.w(TAG, "Rejecting request to create private virtual display "
744                         + "because the virtual display adapter is not available.");
745                 return -1;
746             }
747 
748             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
749                     callback, projection, callingUid, packageName, name, width, height, densityDpi,
750                     surface, flags, uniqueId);
751             if (device == null) {
752                 return -1;
753             }
754 
755             handleDisplayDeviceAddedLocked(device);
756             LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
757             if (display != null) {
758                 return display.getDisplayIdLocked();
759             }
760 
761             // Something weird happened and the logical display was not created.
762             Slog.w(TAG, "Rejecting request to create virtual display "
763                     + "because the logical display was not created.");
764             mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
765             handleDisplayDeviceRemovedLocked(device);
766         }
767         return -1;
768     }
769 
resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)770     private void resizeVirtualDisplayInternal(IBinder appToken,
771             int width, int height, int densityDpi) {
772         synchronized (mSyncRoot) {
773             if (mVirtualDisplayAdapter == null) {
774                 return;
775             }
776 
777             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
778         }
779     }
780 
setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)781     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
782         synchronized (mSyncRoot) {
783             if (mVirtualDisplayAdapter == null) {
784                 return;
785             }
786 
787             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
788         }
789     }
790 
releaseVirtualDisplayInternal(IBinder appToken)791     private void releaseVirtualDisplayInternal(IBinder appToken) {
792         synchronized (mSyncRoot) {
793             if (mVirtualDisplayAdapter == null) {
794                 return;
795             }
796 
797             DisplayDevice device =
798                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
799             if (device != null) {
800                 handleDisplayDeviceRemovedLocked(device);
801             }
802         }
803     }
804 
registerDefaultDisplayAdapters()805     private void registerDefaultDisplayAdapters() {
806         // Register default display adapters.
807         synchronized (mSyncRoot) {
808             // main display adapter
809             registerDisplayAdapterLocked(new LocalDisplayAdapter(
810                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
811 
812             // Standalone VR devices rely on a virtual display as their primary display for
813             // 2D UI. We register virtual display adapter along side the main display adapter
814             // here so that it is ready by the time the system sends the home Intent for
815             // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
816             // the virtual display inside VR before any VR-specific apps even run.
817             mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
818                     mHandler, mDisplayAdapterListener);
819             if (mVirtualDisplayAdapter != null) {
820                 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
821             }
822         }
823     }
824 
registerAdditionalDisplayAdapters()825     private void registerAdditionalDisplayAdapters() {
826         synchronized (mSyncRoot) {
827             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
828                 registerOverlayDisplayAdapterLocked();
829                 registerWifiDisplayAdapterLocked();
830             }
831         }
832     }
833 
registerOverlayDisplayAdapterLocked()834     private void registerOverlayDisplayAdapterLocked() {
835         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
836                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
837     }
838 
registerWifiDisplayAdapterLocked()839     private void registerWifiDisplayAdapterLocked() {
840         if (mContext.getResources().getBoolean(
841                 com.android.internal.R.bool.config_enableWifiDisplay)
842                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
843             mWifiDisplayAdapter = new WifiDisplayAdapter(
844                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
845                     mPersistentDataStore);
846             registerDisplayAdapterLocked(mWifiDisplayAdapter);
847         }
848     }
849 
shouldRegisterNonEssentialDisplayAdaptersLocked()850     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
851         // In safe mode, we disable non-essential display adapters to give the user
852         // an opportunity to fix broken settings or other problems that might affect
853         // system stability.
854         // In only-core mode, we disable non-essential display adapters to minimize
855         // the number of dependencies that are started while in this mode and to
856         // prevent problems that might occur due to the device being encrypted.
857         return !mSafeMode && !mOnlyCore;
858     }
859 
registerDisplayAdapterLocked(DisplayAdapter adapter)860     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
861         mDisplayAdapters.add(adapter);
862         adapter.registerLocked();
863     }
864 
handleDisplayDeviceAdded(DisplayDevice device)865     private void handleDisplayDeviceAdded(DisplayDevice device) {
866         synchronized (mSyncRoot) {
867             handleDisplayDeviceAddedLocked(device);
868         }
869     }
870 
handleDisplayDeviceAddedLocked(DisplayDevice device)871     private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
872         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
873         if (mDisplayDevices.contains(device)) {
874             Slog.w(TAG, "Attempted to add already added display device: " + info);
875             return;
876         }
877 
878         Slog.i(TAG, "Display device added: " + info);
879         device.mDebugLastLoggedDeviceInfo = info;
880 
881         mDisplayDevices.add(device);
882         LogicalDisplay display = addLogicalDisplayLocked(device);
883         Runnable work = updateDisplayStateLocked(device);
884         if (work != null) {
885             work.run();
886         }
887         scheduleTraversalLocked(false);
888     }
889 
handleDisplayDeviceChanged(DisplayDevice device)890     private void handleDisplayDeviceChanged(DisplayDevice device) {
891         synchronized (mSyncRoot) {
892             DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
893             if (!mDisplayDevices.contains(device)) {
894                 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
895                 return;
896             }
897 
898             int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
899             if (diff == DisplayDeviceInfo.DIFF_STATE) {
900                 Slog.i(TAG, "Display device changed state: \"" + info.name
901                         + "\", " + Display.stateToString(info.state));
902             } else if (diff != 0) {
903                 Slog.i(TAG, "Display device changed: " + info);
904             }
905             if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
906                 try {
907                     mPersistentDataStore.setColorMode(device, info.colorMode);
908                 } finally {
909                     mPersistentDataStore.saveIfNeeded();
910                 }
911             }
912             device.mDebugLastLoggedDeviceInfo = info;
913 
914             device.applyPendingDisplayDeviceInfoChangesLocked();
915             if (updateLogicalDisplaysLocked()) {
916                 scheduleTraversalLocked(false);
917             }
918         }
919     }
920 
handleDisplayDeviceRemoved(DisplayDevice device)921     private void handleDisplayDeviceRemoved(DisplayDevice device) {
922         synchronized (mSyncRoot) {
923             handleDisplayDeviceRemovedLocked(device);
924         }
925     }
926 
handleDisplayDeviceRemovedLocked(DisplayDevice device)927     private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
928         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
929         if (!mDisplayDevices.remove(device)) {
930             Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
931             return;
932         }
933 
934         Slog.i(TAG, "Display device removed: " + info);
935         device.mDebugLastLoggedDeviceInfo = info;
936 
937         updateLogicalDisplaysLocked();
938         scheduleTraversalLocked(false);
939     }
940 
applyGlobalDisplayStateLocked(List<Runnable> workQueue)941     private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
942         final int count = mDisplayDevices.size();
943         for (int i = 0; i < count; i++) {
944             DisplayDevice device = mDisplayDevices.get(i);
945             Runnable runnable = updateDisplayStateLocked(device);
946             if (runnable != null) {
947                 workQueue.add(runnable);
948             }
949         }
950     }
951 
updateDisplayStateLocked(DisplayDevice device)952     private Runnable updateDisplayStateLocked(DisplayDevice device) {
953         // Blank or unblank the display immediately to match the state requested
954         // by the display power controller (if known).
955         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
956         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
957             return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
958         }
959         return null;
960     }
961 
962     // Adds a new logical display based on the given display device.
963     // Sends notifications if needed.
addLogicalDisplayLocked(DisplayDevice device)964     private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
965         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
966         boolean isDefault = (deviceInfo.flags
967                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
968         if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
969             Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
970             isDefault = false;
971         }
972 
973         if (!isDefault && mSingleDisplayDemoMode) {
974             Slog.i(TAG, "Not creating a logical display for a secondary display "
975                     + " because single display demo mode is enabled: " + deviceInfo);
976             return null;
977         }
978 
979         final int displayId = assignDisplayIdLocked(isDefault);
980         final int layerStack = assignLayerStackLocked(displayId);
981 
982         LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
983         display.updateLocked(mDisplayDevices);
984         if (!display.isValidLocked()) {
985             // This should never happen currently.
986             Slog.w(TAG, "Ignoring display device because the logical display "
987                     + "created from it was not considered valid: " + deviceInfo);
988             return null;
989         }
990 
991         configureColorModeLocked(display, device);
992         if (isDefault) {
993             recordStableDisplayStatsIfNeededLocked(display);
994         }
995 
996         mLogicalDisplays.put(displayId, display);
997 
998         // Wake up waitForDefaultDisplay.
999         if (isDefault) {
1000             mSyncRoot.notifyAll();
1001         }
1002 
1003         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
1004         return display;
1005     }
1006 
assignDisplayIdLocked(boolean isDefault)1007     private int assignDisplayIdLocked(boolean isDefault) {
1008         return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
1009     }
1010 
assignLayerStackLocked(int displayId)1011     private int assignLayerStackLocked(int displayId) {
1012         // Currently layer stacks and display ids are the same.
1013         // This need not be the case.
1014         return displayId;
1015     }
1016 
configureColorModeLocked(LogicalDisplay display, DisplayDevice device)1017     private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
1018         if (display.getPrimaryDisplayDeviceLocked() == device) {
1019             int colorMode = mPersistentDataStore.getColorMode(device);
1020             if (colorMode == Display.COLOR_MODE_INVALID) {
1021                 if ((device.getDisplayDeviceInfoLocked().flags
1022                      & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1023                     colorMode = mDefaultDisplayDefaultColorMode;
1024                 } else {
1025                     colorMode = Display.COLOR_MODE_DEFAULT;
1026                 }
1027             }
1028             display.setRequestedColorModeLocked(colorMode);
1029         }
1030     }
1031 
1032     // If we've never recorded stable device stats for this device before and they aren't
1033     // explicitly configured, go ahead and record the stable device stats now based on the status
1034     // of the default display at first boot.
recordStableDisplayStatsIfNeededLocked(LogicalDisplay d)1035     private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
1036         if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
1037             DisplayInfo info = d.getDisplayInfoLocked();
1038             setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
1039         }
1040     }
1041 
setStableDisplaySizeLocked(int width, int height)1042     private void setStableDisplaySizeLocked(int width, int height) {
1043         mStableDisplaySize = new Point(width, height);
1044         try {
1045             mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
1046         } finally {
1047             mPersistentDataStore.saveIfNeeded();
1048         }
1049     }
1050 
1051     @VisibleForTesting
getMinimumBrightnessCurveInternal()1052     Curve getMinimumBrightnessCurveInternal() {
1053         return mMinimumBrightnessCurve;
1054     }
1055 
setBrightnessConfigurationForUserInternal( @ullable BrightnessConfiguration c, @UserIdInt int userId, @Nullable String packageName)1056     private void setBrightnessConfigurationForUserInternal(
1057             @Nullable BrightnessConfiguration c, @UserIdInt int userId,
1058             @Nullable String packageName) {
1059         validateBrightnessConfiguration(c);
1060         final int userSerial = getUserManager().getUserSerialNumber(userId);
1061         synchronized (mSyncRoot) {
1062             try {
1063                 mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial,
1064                         packageName);
1065             } finally {
1066                 mPersistentDataStore.saveIfNeeded();
1067             }
1068             if (userId == mCurrentUserId) {
1069                 mDisplayPowerController.setBrightnessConfiguration(c);
1070             }
1071         }
1072     }
1073 
1074     @VisibleForTesting
validateBrightnessConfiguration(BrightnessConfiguration config)1075     void validateBrightnessConfiguration(BrightnessConfiguration config) {
1076         if (config == null) {
1077             return;
1078         }
1079         if (isBrightnessConfigurationTooDark(config)) {
1080             throw new IllegalArgumentException("brightness curve is too dark");
1081         }
1082     }
1083 
isBrightnessConfigurationTooDark(BrightnessConfiguration config)1084     private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
1085         Pair<float[], float[]> curve = config.getCurve();
1086         float[] lux = curve.first;
1087         float[] nits = curve.second;
1088         for (int i = 0; i < lux.length; i++) {
1089             if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
1090                 return true;
1091             }
1092         }
1093         return false;
1094     }
1095 
loadBrightnessConfiguration()1096     private void loadBrightnessConfiguration() {
1097         synchronized (mSyncRoot) {
1098             final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
1099             BrightnessConfiguration config =
1100                     mPersistentDataStore.getBrightnessConfiguration(userSerial);
1101             mDisplayPowerController.setBrightnessConfiguration(config);
1102         }
1103     }
1104 
1105     // Updates all existing logical displays given the current set of display devices.
1106     // Removes invalid logical displays.
1107     // Sends notifications if needed.
updateLogicalDisplaysLocked()1108     private boolean updateLogicalDisplaysLocked() {
1109         boolean changed = false;
1110         for (int i = mLogicalDisplays.size(); i-- > 0; ) {
1111             final int displayId = mLogicalDisplays.keyAt(i);
1112             LogicalDisplay display = mLogicalDisplays.valueAt(i);
1113 
1114             mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
1115             display.updateLocked(mDisplayDevices);
1116             if (!display.isValidLocked()) {
1117                 mLogicalDisplays.removeAt(i);
1118                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
1119                 changed = true;
1120             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
1121                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
1122                 changed = true;
1123             }
1124         }
1125         return changed;
1126     }
1127 
performTraversalLocked(SurfaceControl.Transaction t)1128     private void performTraversalLocked(SurfaceControl.Transaction t) {
1129         // Clear all viewports before configuring displays so that we can keep
1130         // track of which ones we have configured.
1131         clearViewportsLocked();
1132 
1133         // Configure each display device.
1134         final int count = mDisplayDevices.size();
1135         for (int i = 0; i < count; i++) {
1136             DisplayDevice device = mDisplayDevices.get(i);
1137             configureDisplayLocked(t, device);
1138             device.performTraversalLocked(t);
1139         }
1140 
1141         // Tell the input system about these new viewports.
1142         if (mInputManagerInternal != null) {
1143             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
1144         }
1145     }
1146 
setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, boolean inTraversal)1147     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
1148             float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
1149         synchronized (mSyncRoot) {
1150             LogicalDisplay display = mLogicalDisplays.get(displayId);
1151             if (display == null) {
1152                 return;
1153             }
1154             if (display.hasContentLocked() != hasContent) {
1155                 if (DEBUG) {
1156                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
1157                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
1158                 }
1159 
1160                 display.setHasContentLocked(hasContent);
1161                 scheduleTraversalLocked(inTraversal);
1162             }
1163             if (requestedModeId == 0 && requestedRefreshRate != 0) {
1164                 // Scan supported modes returned by display.getInfo() to find a mode with the same
1165                 // size as the default display mode but with the specified refresh rate instead.
1166                 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
1167                         requestedRefreshRate);
1168             }
1169             if (display.getRequestedModeIdLocked() != requestedModeId) {
1170                 if (DEBUG) {
1171                     Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
1172                 }
1173                 display.setRequestedModeIdLocked(requestedModeId);
1174                 scheduleTraversalLocked(inTraversal);
1175             }
1176         }
1177     }
1178 
setDisplayOffsetsInternal(int displayId, int x, int y)1179     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
1180         synchronized (mSyncRoot) {
1181             LogicalDisplay display = mLogicalDisplays.get(displayId);
1182             if (display == null) {
1183                 return;
1184             }
1185             if (display.getDisplayOffsetXLocked() != x
1186                     || display.getDisplayOffsetYLocked() != y) {
1187                 if (DEBUG) {
1188                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
1189                             + x + ", " + y + ")");
1190                 }
1191                 display.setDisplayOffsetsLocked(x, y);
1192                 scheduleTraversalLocked(false);
1193             }
1194         }
1195     }
1196 
1197     // Updates the lists of UIDs that are present on displays.
setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs)1198     private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
1199         synchronized (mSyncRoot) {
1200             mDisplayAccessUIDs.clear();
1201             for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) {
1202                 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i),
1203                         newDisplayAccessUIDs.valueAt(i));
1204             }
1205         }
1206     }
1207 
1208     // Checks if provided UID's content is present on the display and UID has access to it.
isUidPresentOnDisplayInternal(int uid, int displayId)1209     private boolean isUidPresentOnDisplayInternal(int uid, int displayId) {
1210         synchronized (mSyncRoot) {
1211             final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId);
1212             return displayUIDs != null && displayUIDs.indexOf(uid) != -1;
1213         }
1214     }
1215 
clearViewportsLocked()1216     private void clearViewportsLocked() {
1217         mDefaultViewport.valid = false;
1218         mExternalTouchViewport.valid = false;
1219         mVirtualTouchViewports.clear();
1220     }
1221 
configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device)1222     private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
1223         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1224         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
1225 
1226         // Find the logical display that the display device is showing.
1227         // Certain displays only ever show their own content.
1228         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
1229         if (!ownContent) {
1230             if (display != null && !display.hasContentLocked()) {
1231                 // If the display does not have any content of its own, then
1232                 // automatically mirror the default logical display contents.
1233                 display = null;
1234             }
1235             if (display == null) {
1236                 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
1237             }
1238         }
1239 
1240         // Apply the logical display configuration to the display device.
1241         if (display == null) {
1242             // TODO: no logical display for the device, blank it
1243             Slog.w(TAG, "Missing logical display to use for physical display device: "
1244                     + device.getDisplayDeviceInfoLocked());
1245             return;
1246         }
1247         display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
1248 
1249         // Update the viewports if needed.
1250         if (!mDefaultViewport.valid
1251                 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1252             setViewportLocked(mDefaultViewport, display, device);
1253         }
1254         if (!mExternalTouchViewport.valid
1255                 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
1256             setViewportLocked(mExternalTouchViewport, display, device);
1257         }
1258 
1259         if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) {
1260             final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId);
1261             setViewportLocked(viewport, display, device);
1262         }
1263     }
1264 
1265     /** Gets the virtual device viewport or creates it if not yet created. */
getVirtualTouchViewportLocked(@onNull String uniqueId)1266     private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) {
1267         DisplayViewport viewport;
1268         final int count = mVirtualTouchViewports.size();
1269         for (int i = 0; i < count; i++) {
1270             viewport = mVirtualTouchViewports.get(i);
1271             if (uniqueId.equals(viewport.uniqueId)) {
1272                 return viewport;
1273             }
1274         }
1275 
1276         viewport = new DisplayViewport();
1277         viewport.uniqueId = uniqueId;
1278         mVirtualTouchViewports.add(viewport);
1279         return viewport;
1280     }
1281 
setViewportLocked(DisplayViewport viewport, LogicalDisplay display, DisplayDevice device)1282     private static void setViewportLocked(DisplayViewport viewport,
1283             LogicalDisplay display, DisplayDevice device) {
1284         viewport.valid = true;
1285         viewport.displayId = display.getDisplayIdLocked();
1286         device.populateViewportLocked(viewport);
1287     }
1288 
findLogicalDisplayForDeviceLocked(DisplayDevice device)1289     private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
1290         final int count = mLogicalDisplays.size();
1291         for (int i = 0; i < count; i++) {
1292             LogicalDisplay display = mLogicalDisplays.valueAt(i);
1293             if (display.getPrimaryDisplayDeviceLocked() == device) {
1294                 return display;
1295             }
1296         }
1297         return null;
1298     }
1299 
sendDisplayEventLocked(int displayId, int event)1300     private void sendDisplayEventLocked(int displayId, int event) {
1301         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
1302         mHandler.sendMessage(msg);
1303     }
1304 
1305     // Requests that performTraversals be called at a
1306     // later time to apply changes to surfaces and displays.
scheduleTraversalLocked(boolean inTraversal)1307     private void scheduleTraversalLocked(boolean inTraversal) {
1308         if (!mPendingTraversal && mWindowManagerInternal != null) {
1309             mPendingTraversal = true;
1310             if (!inTraversal) {
1311                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
1312             }
1313         }
1314     }
1315 
1316     // Runs on Handler thread.
1317     // Delivers display event notifications to callbacks.
deliverDisplayEvent(int displayId, int event)1318     private void deliverDisplayEvent(int displayId, int event) {
1319         if (DEBUG) {
1320             Slog.d(TAG, "Delivering display event: displayId="
1321                     + displayId + ", event=" + event);
1322         }
1323 
1324         // Grab the lock and copy the callbacks.
1325         final int count;
1326         synchronized (mSyncRoot) {
1327             count = mCallbacks.size();
1328             mTempCallbacks.clear();
1329             for (int i = 0; i < count; i++) {
1330                 mTempCallbacks.add(mCallbacks.valueAt(i));
1331             }
1332         }
1333 
1334         // After releasing the lock, send the notifications out.
1335         for (int i = 0; i < count; i++) {
1336             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1337         }
1338         mTempCallbacks.clear();
1339     }
1340 
getProjectionService()1341     private IMediaProjectionManager getProjectionService() {
1342         if (mProjectionService == null) {
1343             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1344             mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1345         }
1346         return mProjectionService;
1347     }
1348 
getUserManager()1349     private UserManager getUserManager() {
1350         return mContext.getSystemService(UserManager.class);
1351     }
1352 
dumpInternal(PrintWriter pw)1353     private void dumpInternal(PrintWriter pw) {
1354         pw.println("DISPLAY MANAGER (dumpsys display)");
1355 
1356         synchronized (mSyncRoot) {
1357             pw.println("  mOnlyCode=" + mOnlyCore);
1358             pw.println("  mSafeMode=" + mSafeMode);
1359             pw.println("  mPendingTraversal=" + mPendingTraversal);
1360             pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
1361             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1362             pw.println("  mDefaultViewport=" + mDefaultViewport);
1363             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
1364             pw.println("  mVirtualTouchViewports=" + mVirtualTouchViewports);
1365             pw.println("  mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
1366             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
1367             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
1368             pw.println("  mStableDisplaySize=" + mStableDisplaySize);
1369 
1370 
1371             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
1372             ipw.increaseIndent();
1373 
1374             pw.println();
1375             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
1376             for (DisplayAdapter adapter : mDisplayAdapters) {
1377                 pw.println("  " + adapter.getName());
1378                 adapter.dumpLocked(ipw);
1379             }
1380 
1381             pw.println();
1382             pw.println("Display Devices: size=" + mDisplayDevices.size());
1383             for (DisplayDevice device : mDisplayDevices) {
1384                 pw.println("  " + device.getDisplayDeviceInfoLocked());
1385                 device.dumpLocked(ipw);
1386             }
1387 
1388             final int logicalDisplayCount = mLogicalDisplays.size();
1389             pw.println();
1390             pw.println("Logical Displays: size=" + logicalDisplayCount);
1391             for (int i = 0; i < logicalDisplayCount; i++) {
1392                 int displayId = mLogicalDisplays.keyAt(i);
1393                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1394                 pw.println("  Display " + displayId + ":");
1395                 display.dumpLocked(ipw);
1396             }
1397 
1398             final int callbackCount = mCallbacks.size();
1399             pw.println();
1400             pw.println("Callbacks: size=" + callbackCount);
1401             for (int i = 0; i < callbackCount; i++) {
1402                 CallbackRecord callback = mCallbacks.valueAt(i);
1403                 pw.println("  " + i + ": mPid=" + callback.mPid
1404                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
1405             }
1406 
1407             if (mDisplayPowerController != null) {
1408                 mDisplayPowerController.dump(pw);
1409             }
1410 
1411             pw.println();
1412             mPersistentDataStore.dump(pw);
1413         }
1414     }
1415 
getFloatArray(TypedArray array)1416     private static float[] getFloatArray(TypedArray array) {
1417         int length = array.length();
1418         float[] floatArray = new float[length];
1419         for (int i = 0; i < length; i++) {
1420             floatArray[i] = array.getFloat(i, Float.NaN);
1421         }
1422         array.recycle();
1423         return floatArray;
1424     }
1425 
1426     /**
1427      * This is the object that everything in the display manager locks on.
1428      * We make it an inner class within the {@link DisplayManagerService} to so that it is
1429      * clear that the object belongs to the display manager service and that it is
1430      * a unique object with a special purpose.
1431      */
1432     public static final class SyncRoot {
1433     }
1434 
1435     @VisibleForTesting
1436     static class Injector {
getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener)1437         VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
1438                 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
1439             return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
1440         }
1441 
getDefaultDisplayDelayTimeout()1442         long getDefaultDisplayDelayTimeout() {
1443             return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
1444         }
1445     }
1446 
1447     @VisibleForTesting
getDisplayDeviceInfoInternal(int displayId)1448     DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
1449         synchronized (mSyncRoot) {
1450             LogicalDisplay display = mLogicalDisplays.get(displayId);
1451             if (display != null) {
1452                 DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
1453                 return displayDevice.getDisplayDeviceInfoLocked();
1454             }
1455             return null;
1456         }
1457     }
1458 
1459     private final class DisplayManagerHandler extends Handler {
DisplayManagerHandler(Looper looper)1460         public DisplayManagerHandler(Looper looper) {
1461             super(looper, null, true /*async*/);
1462         }
1463 
1464         @Override
handleMessage(Message msg)1465         public void handleMessage(Message msg) {
1466             switch (msg.what) {
1467                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
1468                     registerDefaultDisplayAdapters();
1469                     break;
1470 
1471                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1472                     registerAdditionalDisplayAdapters();
1473                     break;
1474 
1475                 case MSG_DELIVER_DISPLAY_EVENT:
1476                     deliverDisplayEvent(msg.arg1, msg.arg2);
1477                     break;
1478 
1479                 case MSG_REQUEST_TRAVERSAL:
1480                     mWindowManagerInternal.requestTraversalFromDisplayManager();
1481                     break;
1482 
1483                 case MSG_UPDATE_VIEWPORT: {
1484                     synchronized (mSyncRoot) {
1485                         mTempDefaultViewport.copyFrom(mDefaultViewport);
1486                         mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1487                         if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
1488                           mTempVirtualTouchViewports.clear();
1489                           for (DisplayViewport d : mVirtualTouchViewports) {
1490                               mTempVirtualTouchViewports.add(d.makeCopy());
1491                           }
1492                         }
1493                     }
1494                     mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
1495                             mTempExternalTouchViewport, mTempVirtualTouchViewports);
1496                     break;
1497                 }
1498 
1499                 case MSG_LOAD_BRIGHTNESS_CONFIGURATION:
1500                     loadBrightnessConfiguration();
1501                     break;
1502             }
1503         }
1504     }
1505 
1506     private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1507         @Override
onDisplayDeviceEvent(DisplayDevice device, int event)1508         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1509             switch (event) {
1510                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1511                     handleDisplayDeviceAdded(device);
1512                     break;
1513 
1514                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1515                     handleDisplayDeviceChanged(device);
1516                     break;
1517 
1518                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1519                     handleDisplayDeviceRemoved(device);
1520                     break;
1521             }
1522         }
1523 
1524         @Override
onTraversalRequested()1525         public void onTraversalRequested() {
1526             synchronized (mSyncRoot) {
1527                 scheduleTraversalLocked(false);
1528             }
1529         }
1530     }
1531 
1532     private final class CallbackRecord implements DeathRecipient {
1533         public final int mPid;
1534         private final IDisplayManagerCallback mCallback;
1535 
1536         public boolean mWifiDisplayScanRequested;
1537 
CallbackRecord(int pid, IDisplayManagerCallback callback)1538         public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1539             mPid = pid;
1540             mCallback = callback;
1541         }
1542 
1543         @Override
binderDied()1544         public void binderDied() {
1545             if (DEBUG) {
1546                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1547             }
1548             onCallbackDied(this);
1549         }
1550 
notifyDisplayEventAsync(int displayId, int event)1551         public void notifyDisplayEventAsync(int displayId, int event) {
1552             try {
1553                 mCallback.onDisplayEvent(displayId, event);
1554             } catch (RemoteException ex) {
1555                 Slog.w(TAG, "Failed to notify process "
1556                         + mPid + " that displays changed, assuming it died.", ex);
1557                 binderDied();
1558             }
1559         }
1560     }
1561 
1562     @VisibleForTesting
1563     final class BinderService extends IDisplayManager.Stub {
1564         /**
1565          * Returns information about the specified logical display.
1566          *
1567          * @param displayId The logical display id.
1568          * @return The logical display info, or null if the display does not exist.  The
1569          * returned object must be treated as immutable.
1570          */
1571         @Override // Binder call
getDisplayInfo(int displayId)1572         public DisplayInfo getDisplayInfo(int displayId) {
1573             final int callingUid = Binder.getCallingUid();
1574             final long token = Binder.clearCallingIdentity();
1575             try {
1576                 return getDisplayInfoInternal(displayId, callingUid);
1577             } finally {
1578                 Binder.restoreCallingIdentity(token);
1579             }
1580         }
1581 
1582         /**
1583          * Returns the list of all display ids.
1584          */
1585         @Override // Binder call
getDisplayIds()1586         public int[] getDisplayIds() {
1587             final int callingUid = Binder.getCallingUid();
1588             final long token = Binder.clearCallingIdentity();
1589             try {
1590                 return getDisplayIdsInternal(callingUid);
1591             } finally {
1592                 Binder.restoreCallingIdentity(token);
1593             }
1594         }
1595 
1596         /**
1597          * Returns the stable device display size, in pixels.
1598          */
1599         @Override // Binder call
getStableDisplaySize()1600         public Point getStableDisplaySize() {
1601             final long token = Binder.clearCallingIdentity();
1602             try {
1603                 return getStableDisplaySizeInternal();
1604             } finally {
1605                 Binder.restoreCallingIdentity(token);
1606             }
1607         }
1608 
1609         @Override // Binder call
registerCallback(IDisplayManagerCallback callback)1610         public void registerCallback(IDisplayManagerCallback callback) {
1611             if (callback == null) {
1612                 throw new IllegalArgumentException("listener must not be null");
1613             }
1614 
1615             final int callingPid = Binder.getCallingPid();
1616             final long token = Binder.clearCallingIdentity();
1617             try {
1618                 registerCallbackInternal(callback, callingPid);
1619             } finally {
1620                 Binder.restoreCallingIdentity(token);
1621             }
1622         }
1623 
1624         @Override // Binder call
startWifiDisplayScan()1625         public void startWifiDisplayScan() {
1626             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1627                     "Permission required to start wifi display scans");
1628 
1629             final int callingPid = Binder.getCallingPid();
1630             final long token = Binder.clearCallingIdentity();
1631             try {
1632                 startWifiDisplayScanInternal(callingPid);
1633             } finally {
1634                 Binder.restoreCallingIdentity(token);
1635             }
1636         }
1637 
1638         @Override // Binder call
stopWifiDisplayScan()1639         public void stopWifiDisplayScan() {
1640             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1641                     "Permission required to stop wifi display scans");
1642 
1643             final int callingPid = Binder.getCallingPid();
1644             final long token = Binder.clearCallingIdentity();
1645             try {
1646                 stopWifiDisplayScanInternal(callingPid);
1647             } finally {
1648                 Binder.restoreCallingIdentity(token);
1649             }
1650         }
1651 
1652         @Override // Binder call
connectWifiDisplay(String address)1653         public void connectWifiDisplay(String address) {
1654             if (address == null) {
1655                 throw new IllegalArgumentException("address must not be null");
1656             }
1657             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1658                     "Permission required to connect to a wifi display");
1659 
1660             final long token = Binder.clearCallingIdentity();
1661             try {
1662                 connectWifiDisplayInternal(address);
1663             } finally {
1664                 Binder.restoreCallingIdentity(token);
1665             }
1666         }
1667 
1668         @Override // Binder call
disconnectWifiDisplay()1669         public void disconnectWifiDisplay() {
1670             // This request does not require special permissions.
1671             // Any app can request disconnection from the currently active wifi display.
1672             // This exception should no longer be needed once wifi display control moves
1673             // to the media router service.
1674 
1675             final long token = Binder.clearCallingIdentity();
1676             try {
1677                 disconnectWifiDisplayInternal();
1678             } finally {
1679                 Binder.restoreCallingIdentity(token);
1680             }
1681         }
1682 
1683         @Override // Binder call
renameWifiDisplay(String address, String alias)1684         public void renameWifiDisplay(String address, String alias) {
1685             if (address == null) {
1686                 throw new IllegalArgumentException("address must not be null");
1687             }
1688             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1689                     "Permission required to rename to a wifi display");
1690 
1691             final long token = Binder.clearCallingIdentity();
1692             try {
1693                 renameWifiDisplayInternal(address, alias);
1694             } finally {
1695                 Binder.restoreCallingIdentity(token);
1696             }
1697         }
1698 
1699         @Override // Binder call
forgetWifiDisplay(String address)1700         public void forgetWifiDisplay(String address) {
1701             if (address == null) {
1702                 throw new IllegalArgumentException("address must not be null");
1703             }
1704             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1705                     "Permission required to forget to a wifi display");
1706 
1707             final long token = Binder.clearCallingIdentity();
1708             try {
1709                 forgetWifiDisplayInternal(address);
1710             } finally {
1711                 Binder.restoreCallingIdentity(token);
1712             }
1713         }
1714 
1715         @Override // Binder call
pauseWifiDisplay()1716         public void pauseWifiDisplay() {
1717             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1718                     "Permission required to pause a wifi display session");
1719 
1720             final long token = Binder.clearCallingIdentity();
1721             try {
1722                 pauseWifiDisplayInternal();
1723             } finally {
1724                 Binder.restoreCallingIdentity(token);
1725             }
1726         }
1727 
1728         @Override // Binder call
resumeWifiDisplay()1729         public void resumeWifiDisplay() {
1730             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1731                     "Permission required to resume a wifi display session");
1732 
1733             final long token = Binder.clearCallingIdentity();
1734             try {
1735                 resumeWifiDisplayInternal();
1736             } finally {
1737                 Binder.restoreCallingIdentity(token);
1738             }
1739         }
1740 
1741         @Override // Binder call
getWifiDisplayStatus()1742         public WifiDisplayStatus getWifiDisplayStatus() {
1743             // This request does not require special permissions.
1744             // Any app can get information about available wifi displays.
1745 
1746             final long token = Binder.clearCallingIdentity();
1747             try {
1748                 return getWifiDisplayStatusInternal();
1749             } finally {
1750                 Binder.restoreCallingIdentity(token);
1751             }
1752         }
1753 
1754         @Override // Binder call
requestColorMode(int displayId, int colorMode)1755         public void requestColorMode(int displayId, int colorMode) {
1756             mContext.enforceCallingOrSelfPermission(
1757                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
1758                     "Permission required to change the display color mode");
1759             final long token = Binder.clearCallingIdentity();
1760             try {
1761                 requestColorModeInternal(displayId, colorMode);
1762             } finally {
1763                 Binder.restoreCallingIdentity(token);
1764             }
1765         }
1766 
1767         @Override // Binder call
setSaturationLevel(float level)1768         public void setSaturationLevel(float level) {
1769             mContext.enforceCallingOrSelfPermission(
1770                    Manifest.permission.CONTROL_DISPLAY_SATURATION,
1771                    "Permission required to set display saturation level");
1772             final long token = Binder.clearCallingIdentity();
1773             try {
1774                 setSaturationLevelInternal(level);
1775             } finally {
1776                 Binder.restoreCallingIdentity(token);
1777             }
1778         }
1779 
1780         @Override // Binder call
createVirtualDisplay(IVirtualDisplayCallback callback, IMediaProjection projection, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags, String uniqueId)1781         public int createVirtualDisplay(IVirtualDisplayCallback callback,
1782                 IMediaProjection projection, String packageName, String name,
1783                 int width, int height, int densityDpi, Surface surface, int flags,
1784                 String uniqueId) {
1785             final int callingUid = Binder.getCallingUid();
1786             if (!validatePackageName(callingUid, packageName)) {
1787                 throw new SecurityException("packageName must match the calling uid");
1788             }
1789             if (callback == null) {
1790                 throw new IllegalArgumentException("appToken must not be null");
1791             }
1792             if (TextUtils.isEmpty(name)) {
1793                 throw new IllegalArgumentException("name must be non-null and non-empty");
1794             }
1795             if (width <= 0 || height <= 0 || densityDpi <= 0) {
1796                 throw new IllegalArgumentException("width, height, and densityDpi must be "
1797                         + "greater than 0");
1798             }
1799             if (surface != null && surface.isSingleBuffered()) {
1800                 throw new IllegalArgumentException("Surface can't be single-buffered");
1801             }
1802 
1803             if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1804                 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1805 
1806                 // Public displays can't be allowed to show content when locked.
1807                 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
1808                     throw new IllegalArgumentException(
1809                             "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
1810                 }
1811             }
1812             if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1813                 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1814             }
1815 
1816             if (projection != null) {
1817                 try {
1818                     if (!getProjectionService().isValidMediaProjection(projection)) {
1819                         throw new SecurityException("Invalid media projection");
1820                     }
1821                     flags = projection.applyVirtualDisplayFlags(flags);
1822                 } catch (RemoteException e) {
1823                     throw new SecurityException("unable to validate media projection or flags");
1824                 }
1825             }
1826 
1827             if (callingUid != Process.SYSTEM_UID &&
1828                     (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1829                 if (!canProjectVideo(projection)) {
1830                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1831                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1832                             + "MediaProjection token in order to create a screen sharing virtual "
1833                             + "display.");
1834                 }
1835             }
1836             if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1837                 if (!canProjectSecureVideo(projection)) {
1838                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1839                             + "or an appropriate MediaProjection token to create a "
1840                             + "secure virtual display.");
1841                 }
1842             }
1843 
1844             final long token = Binder.clearCallingIdentity();
1845             try {
1846                 return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
1847                         name, width, height, densityDpi, surface, flags, uniqueId);
1848             } finally {
1849                 Binder.restoreCallingIdentity(token);
1850             }
1851         }
1852 
1853         @Override // Binder call
resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)1854         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
1855                 int width, int height, int densityDpi) {
1856             final long token = Binder.clearCallingIdentity();
1857             try {
1858                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
1859             } finally {
1860                 Binder.restoreCallingIdentity(token);
1861             }
1862         }
1863 
1864         @Override // Binder call
setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)1865         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
1866             if (surface != null && surface.isSingleBuffered()) {
1867                 throw new IllegalArgumentException("Surface can't be single-buffered");
1868             }
1869             final long token = Binder.clearCallingIdentity();
1870             try {
1871                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
1872             } finally {
1873                 Binder.restoreCallingIdentity(token);
1874             }
1875         }
1876 
1877         @Override // Binder call
releaseVirtualDisplay(IVirtualDisplayCallback callback)1878         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
1879             final long token = Binder.clearCallingIdentity();
1880             try {
1881                 releaseVirtualDisplayInternal(callback.asBinder());
1882             } finally {
1883                 Binder.restoreCallingIdentity(token);
1884             }
1885         }
1886 
1887         @Override // Binder call
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1888         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1889             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1890 
1891             final long token = Binder.clearCallingIdentity();
1892             try {
1893                 dumpInternal(pw);
1894             } finally {
1895                 Binder.restoreCallingIdentity(token);
1896             }
1897         }
1898 
1899         @Override // Binder call
getBrightnessEvents(String callingPackage)1900         public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
1901             mContext.enforceCallingOrSelfPermission(
1902                     Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
1903                     "Permission to read brightness events.");
1904 
1905             final int callingUid = Binder.getCallingUid();
1906             AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
1907             final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
1908                     callingUid, callingPackage);
1909             final boolean hasUsageStats;
1910             if (mode == AppOpsManager.MODE_DEFAULT) {
1911                 // The default behavior here is to check if PackageManager has given the app
1912                 // permission.
1913                 hasUsageStats = mContext.checkCallingPermission(
1914                         Manifest.permission.PACKAGE_USAGE_STATS)
1915                         == PackageManager.PERMISSION_GRANTED;
1916             } else {
1917                 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED;
1918             }
1919 
1920             final int userId = UserHandle.getUserId(callingUid);
1921             final long token = Binder.clearCallingIdentity();
1922             try {
1923                 synchronized (mSyncRoot) {
1924                     return mDisplayPowerController.getBrightnessEvents(userId, hasUsageStats);
1925                 }
1926             } finally {
1927                 Binder.restoreCallingIdentity(token);
1928             }
1929         }
1930 
1931         @Override // Binder call
getAmbientBrightnessStats()1932         public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
1933             mContext.enforceCallingOrSelfPermission(
1934                     Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS,
1935                     "Permission required to to access ambient light stats.");
1936             final int callingUid = Binder.getCallingUid();
1937             final int userId = UserHandle.getUserId(callingUid);
1938             final long token = Binder.clearCallingIdentity();
1939             try {
1940                 synchronized (mSyncRoot) {
1941                     return mDisplayPowerController.getAmbientBrightnessStats(userId);
1942                 }
1943             } finally {
1944                 Binder.restoreCallingIdentity(token);
1945             }
1946         }
1947 
1948         @Override // Binder call
setBrightnessConfigurationForUser( BrightnessConfiguration c, @UserIdInt int userId, String packageName)1949         public void setBrightnessConfigurationForUser(
1950                 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
1951             mContext.enforceCallingOrSelfPermission(
1952                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
1953                     "Permission required to change the display's brightness configuration");
1954             if (userId != UserHandle.getCallingUserId()) {
1955                 mContext.enforceCallingOrSelfPermission(
1956                         Manifest.permission.INTERACT_ACROSS_USERS,
1957                         "Permission required to change the display brightness"
1958                         + " configuration of another user");
1959             }
1960             if (packageName != null && !validatePackageName(getCallingUid(), packageName)) {
1961                 packageName = null;
1962             }
1963             final long token = Binder.clearCallingIdentity();
1964             try {
1965                 setBrightnessConfigurationForUserInternal(c, userId, packageName);
1966             } finally {
1967                 Binder.restoreCallingIdentity(token);
1968             }
1969         }
1970 
1971         @Override // Binder call
getBrightnessConfigurationForUser(int userId)1972         public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
1973             mContext.enforceCallingOrSelfPermission(
1974                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
1975                     "Permission required to read the display's brightness configuration");
1976             if (userId != UserHandle.getCallingUserId()) {
1977                 mContext.enforceCallingOrSelfPermission(
1978                         Manifest.permission.INTERACT_ACROSS_USERS,
1979                         "Permission required to read the display brightness"
1980                                 + " configuration of another user");
1981             }
1982             final long token = Binder.clearCallingIdentity();
1983             try {
1984                 final int userSerial = getUserManager().getUserSerialNumber(userId);
1985                 synchronized (mSyncRoot) {
1986                     BrightnessConfiguration config =
1987                             mPersistentDataStore.getBrightnessConfiguration(userSerial);
1988                     if (config == null) {
1989                         config = mDisplayPowerController.getDefaultBrightnessConfiguration();
1990                     }
1991                     return config;
1992                 }
1993             } finally {
1994                 Binder.restoreCallingIdentity(token);
1995             }
1996         }
1997 
1998         @Override // Binder call
getDefaultBrightnessConfiguration()1999         public BrightnessConfiguration getDefaultBrightnessConfiguration() {
2000             mContext.enforceCallingOrSelfPermission(
2001                     Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2002                     "Permission required to read the display's default brightness configuration");
2003             final long token = Binder.clearCallingIdentity();
2004             try {
2005                 synchronized (mSyncRoot) {
2006                     return mDisplayPowerController.getDefaultBrightnessConfiguration();
2007                 }
2008             } finally {
2009                 Binder.restoreCallingIdentity(token);
2010             }
2011         }
2012 
2013         @Override // Binder call
setTemporaryBrightness(int brightness)2014         public void setTemporaryBrightness(int brightness) {
2015             mContext.enforceCallingOrSelfPermission(
2016                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2017                     "Permission required to set the display's brightness");
2018             final long token = Binder.clearCallingIdentity();
2019             try {
2020                 synchronized (mSyncRoot) {
2021                     mDisplayPowerController.setTemporaryBrightness(brightness);
2022                 }
2023             } finally {
2024                 Binder.restoreCallingIdentity(token);
2025             }
2026         }
2027 
2028         @Override // Binder call
setTemporaryAutoBrightnessAdjustment(float adjustment)2029         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
2030             mContext.enforceCallingOrSelfPermission(
2031                     Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2032                     "Permission required to set the display's auto brightness adjustment");
2033             final long token = Binder.clearCallingIdentity();
2034             try {
2035                 synchronized (mSyncRoot) {
2036                     mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment);
2037                 }
2038             } finally {
2039                 Binder.restoreCallingIdentity(token);
2040             }
2041         }
2042 
2043         @Override // Binder call
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2044         public void onShellCommand(FileDescriptor in, FileDescriptor out,
2045                 FileDescriptor err, String[] args, ShellCallback callback,
2046                 ResultReceiver resultReceiver) {
2047             final long token = Binder.clearCallingIdentity();
2048             try {
2049                 DisplayManagerShellCommand command = new DisplayManagerShellCommand(this);
2050                 command.exec(this, in, out, err, args, callback, resultReceiver);
2051             } finally {
2052                 Binder.restoreCallingIdentity(token);
2053             }
2054         }
2055 
2056         @Override // Binder call
getMinimumBrightnessCurve()2057         public Curve getMinimumBrightnessCurve() {
2058             final long token = Binder.clearCallingIdentity();
2059             try {
2060                 return getMinimumBrightnessCurveInternal();
2061             } finally {
2062                 Binder.restoreCallingIdentity(token);
2063             }
2064         }
2065 
setBrightness(int brightness)2066         void setBrightness(int brightness) {
2067             Settings.System.putIntForUser(mContext.getContentResolver(),
2068                     Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
2069         }
2070 
resetBrightnessConfiguration()2071         void resetBrightnessConfiguration() {
2072             setBrightnessConfigurationForUserInternal(null, mContext.getUserId(),
2073                     mContext.getPackageName());
2074         }
2075 
validatePackageName(int uid, String packageName)2076         private boolean validatePackageName(int uid, String packageName) {
2077             if (packageName != null) {
2078                 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
2079                 if (packageNames != null) {
2080                     for (String n : packageNames) {
2081                         if (n.equals(packageName)) {
2082                             return true;
2083                         }
2084                     }
2085                 }
2086             }
2087             return false;
2088         }
2089 
canProjectVideo(IMediaProjection projection)2090         private boolean canProjectVideo(IMediaProjection projection) {
2091             if (projection != null) {
2092                 try {
2093                     if (projection.canProjectVideo()) {
2094                         return true;
2095                     }
2096                 } catch (RemoteException e) {
2097                     Slog.e(TAG, "Unable to query projection service for permissions", e);
2098                 }
2099             }
2100             if (mContext.checkCallingPermission(
2101                     android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
2102                     == PackageManager.PERMISSION_GRANTED) {
2103                 return true;
2104             }
2105             return canProjectSecureVideo(projection);
2106         }
2107 
canProjectSecureVideo(IMediaProjection projection)2108         private boolean canProjectSecureVideo(IMediaProjection projection) {
2109             if (projection != null) {
2110                 try {
2111                     if (projection.canProjectSecureVideo()){
2112                         return true;
2113                     }
2114                 } catch (RemoteException e) {
2115                     Slog.e(TAG, "Unable to query projection service for permissions", e);
2116                 }
2117             }
2118             return mContext.checkCallingPermission(
2119                     android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
2120                     == PackageManager.PERMISSION_GRANTED;
2121         }
2122     }
2123 
2124     private final class LocalService extends DisplayManagerInternal {
2125         @Override
initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)2126         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
2127                 SensorManager sensorManager) {
2128             synchronized (mSyncRoot) {
2129                 DisplayBlanker blanker = new DisplayBlanker() {
2130                     @Override
2131                     public void requestDisplayState(int state, int brightness) {
2132                         // The order of operations is important for legacy reasons.
2133                         if (state == Display.STATE_OFF) {
2134                             requestGlobalDisplayStateInternal(state, brightness);
2135                         }
2136 
2137                         callbacks.onDisplayStateChange(state);
2138 
2139                         if (state != Display.STATE_OFF) {
2140                             requestGlobalDisplayStateInternal(state, brightness);
2141                         }
2142                     }
2143                 };
2144                 mDisplayPowerController = new DisplayPowerController(
2145                         mContext, callbacks, handler, sensorManager, blanker);
2146             }
2147 
2148             mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
2149         }
2150 
2151         @Override
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)2152         public boolean requestPowerState(DisplayPowerRequest request,
2153                 boolean waitForNegativeProximity) {
2154             synchronized (mSyncRoot) {
2155                 return mDisplayPowerController.requestPowerState(request,
2156                         waitForNegativeProximity);
2157             }
2158         }
2159 
2160         @Override
isProximitySensorAvailable()2161         public boolean isProximitySensorAvailable() {
2162             synchronized (mSyncRoot) {
2163                 return mDisplayPowerController.isProximitySensorAvailable();
2164             }
2165         }
2166 
2167         @Override
getDisplayInfo(int displayId)2168         public DisplayInfo getDisplayInfo(int displayId) {
2169             return getDisplayInfoInternal(displayId, Process.myUid());
2170         }
2171 
2172         @Override
registerDisplayTransactionListener(DisplayTransactionListener listener)2173         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
2174             if (listener == null) {
2175                 throw new IllegalArgumentException("listener must not be null");
2176             }
2177 
2178             registerDisplayTransactionListenerInternal(listener);
2179         }
2180 
2181         @Override
unregisterDisplayTransactionListener(DisplayTransactionListener listener)2182         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
2183             if (listener == null) {
2184                 throw new IllegalArgumentException("listener must not be null");
2185             }
2186 
2187             unregisterDisplayTransactionListenerInternal(listener);
2188         }
2189 
2190         @Override
setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)2191         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
2192             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
2193         }
2194 
2195         @Override
getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo)2196         public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
2197             getNonOverrideDisplayInfoInternal(displayId, outInfo);
2198         }
2199 
2200         @Override
performTraversal(SurfaceControl.Transaction t)2201         public void performTraversal(SurfaceControl.Transaction t) {
2202             performTraversalInternal(t);
2203         }
2204 
2205         @Override
setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, boolean inTraversal)2206         public void setDisplayProperties(int displayId, boolean hasContent,
2207                 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
2208             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
2209                     requestedMode, inTraversal);
2210         }
2211 
2212         @Override
setDisplayOffsets(int displayId, int x, int y)2213         public void setDisplayOffsets(int displayId, int x, int y) {
2214             setDisplayOffsetsInternal(displayId, x, y);
2215         }
2216 
2217         @Override
setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs)2218         public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
2219             setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
2220         }
2221 
2222         @Override
isUidPresentOnDisplay(int uid, int displayId)2223         public boolean isUidPresentOnDisplay(int uid, int displayId) {
2224             return isUidPresentOnDisplayInternal(uid, displayId);
2225         }
2226 
2227         @Override
persistBrightnessTrackerState()2228         public void persistBrightnessTrackerState() {
2229             synchronized (mSyncRoot) {
2230                 mDisplayPowerController.persistBrightnessTrackerState();
2231             }
2232         }
2233 
2234         @Override
onOverlayChanged()2235         public void onOverlayChanged() {
2236             synchronized (mSyncRoot) {
2237                 for (int i = 0; i < mDisplayDevices.size(); i++) {
2238                     mDisplayDevices.get(i).onOverlayChangedLocked();
2239                 }
2240             }
2241         }
2242     }
2243 }
2244