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