OSDN Git Service

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