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