2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.display;
19 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
20 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
22 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
23 import static android.hardware.display.DisplayManager
24 .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.internal.util.DumpUtils;
28 import com.android.internal.util.IndentingPrintWriter;
30 import android.Manifest;
31 import android.annotation.NonNull;
32 import android.annotation.Nullable;
33 import android.annotation.UserIdInt;
34 import android.app.AppOpsManager;
35 import android.content.Context;
36 import android.content.pm.PackageManager;
37 import android.content.pm.ParceledListSlice;
38 import android.content.res.Resources;
39 import android.content.res.TypedArray;
40 import android.graphics.Point;
41 import android.hardware.SensorManager;
42 import android.hardware.display.AmbientBrightnessDayStats;
43 import android.hardware.display.BrightnessChangeEvent;
44 import android.hardware.display.BrightnessConfiguration;
45 import android.hardware.display.Curve;
46 import android.hardware.display.DisplayManagerGlobal;
47 import android.hardware.display.DisplayManagerInternal;
48 import android.hardware.display.DisplayViewport;
49 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
50 import android.hardware.display.IDisplayManager;
51 import android.hardware.display.IDisplayManagerCallback;
52 import android.hardware.display.IVirtualDisplayCallback;
53 import android.hardware.display.WifiDisplayStatus;
54 import android.hardware.input.InputManagerInternal;
55 import android.media.projection.IMediaProjection;
56 import android.media.projection.IMediaProjectionManager;
57 import android.os.Binder;
58 import android.os.Handler;
59 import android.os.IBinder;
60 import android.os.IBinder.DeathRecipient;
61 import android.os.Looper;
62 import android.os.Message;
63 import android.os.PowerManager;
64 import android.os.Process;
65 import android.os.RemoteException;
66 import android.os.ResultReceiver;
67 import android.os.ServiceManager;
68 import android.os.ShellCallback;
69 import android.os.SystemClock;
70 import android.os.SystemProperties;
71 import android.os.Trace;
72 import android.os.UserHandle;
73 import android.os.UserManager;
74 import android.provider.Settings;
75 import android.text.TextUtils;
76 import android.util.IntArray;
77 import android.util.Pair;
78 import android.util.Slog;
79 import android.util.SparseArray;
80 import android.util.Spline;
81 import android.view.Display;
82 import android.view.DisplayInfo;
83 import android.view.Surface;
84 import android.view.SurfaceControl;
86 import com.android.internal.util.Preconditions;
87 import com.android.server.AnimationThread;
88 import com.android.server.DisplayThread;
89 import com.android.server.LocalServices;
90 import com.android.server.SystemService;
91 import com.android.server.UiThread;
92 import com.android.server.wm.WindowManagerInternal;
93 import com.android.server.wm.SurfaceAnimationThread;
95 import java.io.FileDescriptor;
96 import java.io.PrintWriter;
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.List;
100 import java.util.concurrent.CopyOnWriteArrayList;
103 * Manages attached displays.
105 * The {@link DisplayManagerService} manages the global lifecycle of displays,
106 * decides how to configure logical displays based on the physical display devices currently
107 * attached, sends notifications to the system and to applications when the state
108 * changes, and so on.
110 * The display manager service relies on a collection of {@link DisplayAdapter} components,
111 * for discovering and configuring physical display devices attached to the system.
112 * There are separate display adapters for each manner that devices are attached:
113 * one display adapter for built-in local displays, one for simulated non-functional
114 * displays when the system is headless, one for simulated overlay displays used for
115 * development, one for wifi displays, etc.
117 * Display adapters are only weakly coupled to the display manager service.
118 * Display adapters communicate changes in display device state to the display manager
119 * service asynchronously via a {@link DisplayAdapter.Listener} registered
120 * by the display manager service. This separation of concerns is important for
121 * two main reasons. First, it neatly encapsulates the responsibilities of these
122 * two classes: display adapters handle individual display devices whereas
123 * the display manager service handles the global state. Second, it eliminates
124 * the potential for deadlocks resulting from asynchronous display device discovery.
127 * <h3>Synchronization</h3>
129 * Because the display manager may be accessed by multiple threads, the synchronization
130 * story gets a little complicated. In particular, the window manager may call into
131 * the display manager while holding a surface transaction with the expectation that
132 * it can apply changes immediately. Unfortunately, that means we can't just do
133 * everything asynchronously (*grump*).
135 * To make this work, all of the objects that belong to the display manager must
136 * use the same lock. We call this lock the synchronization root and it has a unique
137 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are
138 * named with the "Locked" suffix.
140 * Where things get tricky is that the display manager is not allowed to make
141 * any potentially reentrant calls, especially into the window manager. We generally
142 * avoid this by making all potentially reentrant out-calls asynchronous.
145 public final class DisplayManagerService extends SystemService {
146 private static final String TAG = "DisplayManagerService";
147 private static final boolean DEBUG = false;
149 // When this system property is set to 0, WFD is forcibly disabled on boot.
150 // When this system property is set to 1, WFD is forcibly enabled on boot.
151 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
152 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
154 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
156 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
157 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
158 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
159 private static final int MSG_REQUEST_TRAVERSAL = 4;
160 private static final int MSG_UPDATE_VIEWPORT = 5;
161 private static final int MSG_REGISTER_BRIGHTNESS_TRACKER = 6;
162 private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 7;
164 private final Context mContext;
165 private final DisplayManagerHandler mHandler;
166 private final Handler mUiHandler;
167 private final DisplayAdapterListener mDisplayAdapterListener;
168 private WindowManagerInternal mWindowManagerInternal;
169 private InputManagerInternal mInputManagerInternal;
170 private IMediaProjectionManager mProjectionService;
172 // The synchronization root for the display manager.
173 // This lock guards most of the display manager's state.
174 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
175 // into WindowManagerService methods that require mWindowMap while holding this unless you are
176 // very very sure that no deadlock can occur.
177 private final SyncRoot mSyncRoot = new SyncRoot();
179 // True if in safe mode.
180 // This option may disable certain display adapters.
181 public boolean mSafeMode;
183 // True if we are in a special boot mode where only core applications and
184 // services should be started. This option may disable certain display adapters.
185 public boolean mOnlyCore;
187 // True if the display manager service should pretend there is only one display
188 // and only tell applications about the existence of the default logical display.
189 // The display manager can still mirror content to secondary displays but applications
190 // cannot present unique content on those displays.
191 // Used for demonstration purposes only.
192 private final boolean mSingleDisplayDemoMode;
194 // All callback records indexed by calling process id.
195 public final SparseArray<CallbackRecord> mCallbacks =
196 new SparseArray<CallbackRecord>();
198 // List of all currently registered display adapters.
199 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
201 // List of all currently connected display devices.
202 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
204 // List of all logical displays indexed by logical display id.
205 private final SparseArray<LogicalDisplay> mLogicalDisplays =
206 new SparseArray<LogicalDisplay>();
207 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
209 // List of all display transaction listeners.
210 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
211 new CopyOnWriteArrayList<DisplayTransactionListener>();
213 // Display power controller.
214 private DisplayPowerController mDisplayPowerController;
216 // The overall display state, independent of changes that might influence one
217 // display or another in particular.
218 private int mGlobalDisplayState = Display.STATE_ON;
220 // The overall display brightness.
221 // For now, this only applies to the built-in display but we may split it up eventually.
222 private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
224 // Set to true when there are pending display changes that have yet to be applied
225 // to the surface flinger state.
226 private boolean mPendingTraversal;
228 // The Wifi display adapter, or null if not registered.
229 private WifiDisplayAdapter mWifiDisplayAdapter;
231 // The number of active wifi display scan requests.
232 private int mWifiDisplayScanRequestCount;
234 // The virtual display adapter, or null if not registered.
235 private VirtualDisplayAdapter mVirtualDisplayAdapter;
237 // The User ID of the current user
238 private @UserIdInt int mCurrentUserId;
240 // The stable device screen height and width. These are not tied to a specific display, even
241 // the default display, because they need to be stable over the course of the device's entire
242 // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
244 private Point mStableDisplaySize = new Point();
246 // Viewports of the default display and the display that should receive touch
247 // input from an external source. Used by the input system.
248 private final DisplayViewport mDefaultViewport = new DisplayViewport();
249 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
250 private final ArrayList<DisplayViewport> mVirtualTouchViewports = new ArrayList<>();
252 // Persistent data store for all internal settings maintained by the display manager service.
253 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
255 // Temporary callback list, used when sending display events to applications.
256 // May be used outside of the lock but only on the handler thread.
257 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
259 // Temporary display info, used for comparing display configurations.
260 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
262 // Temporary viewports, used when sending new viewport information to the
263 // input system. May be used outside of the lock but only on the handler thread.
264 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
265 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
266 private final ArrayList<DisplayViewport> mTempVirtualTouchViewports = new ArrayList<>();
268 // The default color mode for default displays. Overrides the usual
269 // Display.Display.COLOR_MODE_DEFAULT for displays with the
270 // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
271 private final int mDefaultDisplayDefaultColorMode;
273 // Temporary list of deferred work to perform when setting the display state.
274 // Only used by requestDisplayState. The field is self-synchronized and only
275 // intended for use inside of the requestGlobalDisplayStateInternal function.
276 private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
278 // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
279 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
281 private final Injector mInjector;
283 // The minimum brightness curve, which guarantess that any brightness curve that dips below it
284 // is rejected by the system.
285 private final Curve mMinimumBrightnessCurve;
286 private final Spline mMinimumBrightnessSpline;
288 public DisplayManagerService(Context context) {
289 this(context, new Injector());
293 DisplayManagerService(Context context, Injector injector) {
295 mInjector = injector;
297 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
298 mUiHandler = UiThread.getHandler();
299 mDisplayAdapterListener = new DisplayAdapterListener();
300 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
301 Resources resources = mContext.getResources();
302 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
303 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
304 float[] lux = getFloatArray(resources.obtainTypedArray(
305 com.android.internal.R.array.config_minimumBrightnessCurveLux));
306 float[] nits = getFloatArray(resources.obtainTypedArray(
307 com.android.internal.R.array.config_minimumBrightnessCurveNits));
308 mMinimumBrightnessCurve = new Curve(lux, nits);
309 mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
311 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
312 mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
313 mCurrentUserId = UserHandle.USER_SYSTEM;
316 public void setupSchedulerPolicies() {
317 // android.display and android.anim is critical to user experience and we should make sure
318 // it is not in the default foregroup groups, add it to top-app to make sure it uses all
319 // the cores and scheduling settings for top-app when it runs.
320 Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
321 Process.THREAD_GROUP_TOP_APP);
322 Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
323 Process.THREAD_GROUP_TOP_APP);
324 Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
325 Process.THREAD_GROUP_TOP_APP);
329 public void onStart() {
330 // We need to pre-load the persistent data store so it's ready before the default display
331 // adapter is up so that we have it's configuration. We could load it lazily, but since
332 // we're going to have to read it in eventually we may as well do it here rather than after
333 // we've waited for the display to register itself with us.
334 synchronized(mSyncRoot) {
335 mPersistentDataStore.loadIfNeeded();
336 loadStableDisplayValuesLocked();
338 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
340 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
341 true /*allowIsolated*/);
342 publishLocalService(DisplayManagerInternal.class, new LocalService());
343 publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
347 public void onBootPhase(int phase) {
348 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
349 synchronized (mSyncRoot) {
350 long timeout = SystemClock.uptimeMillis()
351 + mInjector.getDefaultDisplayDelayTimeout();
352 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
353 mVirtualDisplayAdapter == null) {
354 long delay = timeout - SystemClock.uptimeMillis();
356 throw new RuntimeException("Timeout waiting for default display "
357 + "to be initialized. DefaultDisplay="
358 + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
359 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
362 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
365 mSyncRoot.wait(delay);
366 } catch (InterruptedException ex) {
374 public void onSwitchUser(@UserIdInt int newUserId) {
375 final int userSerial = getUserManager().getUserSerialNumber(newUserId);
376 synchronized (mSyncRoot) {
377 if (mCurrentUserId != newUserId) {
378 mCurrentUserId = newUserId;
379 BrightnessConfiguration config =
380 mPersistentDataStore.getBrightnessConfiguration(userSerial);
381 mDisplayPowerController.setBrightnessConfiguration(config);
383 mDisplayPowerController.onSwitchUser(newUserId);
387 // TODO: Use dependencies or a boot phase
388 public void windowManagerAndInputReady() {
389 synchronized (mSyncRoot) {
390 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
391 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
392 scheduleTraversalLocked(false);
397 * Called when the system is ready to go.
399 public void systemReady(boolean safeMode, boolean onlyCore) {
400 synchronized (mSyncRoot) {
401 mSafeMode = safeMode;
402 mOnlyCore = onlyCore;
405 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
406 mHandler.sendEmptyMessage(MSG_REGISTER_BRIGHTNESS_TRACKER);
410 Handler getDisplayHandler() {
414 private void loadStableDisplayValuesLocked() {
415 final Point size = mPersistentDataStore.getStableDisplaySize();
416 if (size.x > 0 && size.y > 0) {
417 // Just set these values directly so we don't write the display persistent data again
419 mStableDisplaySize.set(size.x, size.y);
421 final Resources res = mContext.getResources();
422 final int width = res.getInteger(
423 com.android.internal.R.integer.config_stableDeviceDisplayWidth);
424 final int height = res.getInteger(
425 com.android.internal.R.integer.config_stableDeviceDisplayHeight);
426 if (width > 0 && height > 0) {
427 setStableDisplaySizeLocked(width, height);
432 private Point getStableDisplaySizeInternal() {
433 Point r = new Point();
434 synchronized (mSyncRoot) {
435 if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
436 r.set(mStableDisplaySize.x, mStableDisplaySize.y);
442 private void registerDisplayTransactionListenerInternal(
443 DisplayTransactionListener listener) {
444 // List is self-synchronized copy-on-write.
445 mDisplayTransactionListeners.add(listener);
448 private void unregisterDisplayTransactionListenerInternal(
449 DisplayTransactionListener listener) {
450 // List is self-synchronized copy-on-write.
451 mDisplayTransactionListeners.remove(listener);
454 private void setDisplayInfoOverrideFromWindowManagerInternal(
455 int displayId, DisplayInfo info) {
456 synchronized (mSyncRoot) {
457 LogicalDisplay display = mLogicalDisplays.get(displayId);
458 if (display != null) {
459 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
460 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
461 scheduleTraversalLocked(false);
468 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
470 private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
471 synchronized (mSyncRoot) {
472 final LogicalDisplay display = mLogicalDisplays.get(displayId);
473 if (display != null) {
474 display.getNonOverrideDisplayInfoLocked(outInfo);
480 void performTraversalInternal(SurfaceControl.Transaction t) {
481 synchronized (mSyncRoot) {
482 if (!mPendingTraversal) {
485 mPendingTraversal = false;
487 performTraversalLocked(t);
490 // List is self-synchronized copy-on-write.
491 for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
492 listener.onDisplayTransaction();
496 private void requestGlobalDisplayStateInternal(int state, int brightness) {
497 if (state == Display.STATE_UNKNOWN) {
498 state = Display.STATE_ON;
500 if (state == Display.STATE_OFF) {
501 brightness = PowerManager.BRIGHTNESS_OFF;
502 } else if (brightness < 0) {
503 brightness = PowerManager.BRIGHTNESS_DEFAULT;
504 } else if (brightness > PowerManager.BRIGHTNESS_ON) {
505 brightness = PowerManager.BRIGHTNESS_ON;
508 synchronized (mTempDisplayStateWorkQueue) {
510 // Update the display state within the lock.
511 // Note that we do not need to schedule traversals here although it
512 // may happen as a side-effect of displays changing state.
513 synchronized (mSyncRoot) {
514 if (mGlobalDisplayState == state
515 && mGlobalDisplayBrightness == brightness) {
519 Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
520 + Display.stateToString(state)
521 + ", brightness=" + brightness + ")");
522 mGlobalDisplayState = state;
523 mGlobalDisplayBrightness = brightness;
524 applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
527 // Setting the display power state can take hundreds of milliseconds
528 // to complete so we defer the most expensive part of the work until
529 // after we have exited the critical section to avoid blocking other
530 // threads for a long time.
531 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
532 mTempDisplayStateWorkQueue.get(i).run();
534 Trace.traceEnd(Trace.TRACE_TAG_POWER);
536 mTempDisplayStateWorkQueue.clear();
541 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
542 synchronized (mSyncRoot) {
543 LogicalDisplay display = mLogicalDisplays.get(displayId);
544 if (display != null) {
545 DisplayInfo info = display.getDisplayInfoLocked();
546 if (info.hasAccess(callingUid)
547 || isUidPresentOnDisplayInternal(callingUid, displayId)) {
555 private int[] getDisplayIdsInternal(int callingUid) {
556 synchronized (mSyncRoot) {
557 final int count = mLogicalDisplays.size();
558 int[] displayIds = new int[count];
560 for (int i = 0; i < count; i++) {
561 LogicalDisplay display = mLogicalDisplays.valueAt(i);
562 DisplayInfo info = display.getDisplayInfoLocked();
563 if (info.hasAccess(callingUid)) {
564 displayIds[n++] = mLogicalDisplays.keyAt(i);
568 displayIds = Arrays.copyOfRange(displayIds, 0, n);
574 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
575 synchronized (mSyncRoot) {
576 if (mCallbacks.get(callingPid) != null) {
577 throw new SecurityException("The calling process has already "
578 + "registered an IDisplayManagerCallback.");
581 CallbackRecord record = new CallbackRecord(callingPid, callback);
583 IBinder binder = callback.asBinder();
584 binder.linkToDeath(record, 0);
585 } catch (RemoteException ex) {
587 throw new RuntimeException(ex);
590 mCallbacks.put(callingPid, record);
594 private void onCallbackDied(CallbackRecord record) {
595 synchronized (mSyncRoot) {
596 mCallbacks.remove(record.mPid);
597 stopWifiDisplayScanLocked(record);
601 private void startWifiDisplayScanInternal(int callingPid) {
602 synchronized (mSyncRoot) {
603 CallbackRecord record = mCallbacks.get(callingPid);
604 if (record == null) {
605 throw new IllegalStateException("The calling process has not "
606 + "registered an IDisplayManagerCallback.");
608 startWifiDisplayScanLocked(record);
612 private void startWifiDisplayScanLocked(CallbackRecord record) {
613 if (!record.mWifiDisplayScanRequested) {
614 record.mWifiDisplayScanRequested = true;
615 if (mWifiDisplayScanRequestCount++ == 0) {
616 if (mWifiDisplayAdapter != null) {
617 mWifiDisplayAdapter.requestStartScanLocked();
623 private void stopWifiDisplayScanInternal(int callingPid) {
624 synchronized (mSyncRoot) {
625 CallbackRecord record = mCallbacks.get(callingPid);
626 if (record == null) {
627 throw new IllegalStateException("The calling process has not "
628 + "registered an IDisplayManagerCallback.");
630 stopWifiDisplayScanLocked(record);
634 private void stopWifiDisplayScanLocked(CallbackRecord record) {
635 if (record.mWifiDisplayScanRequested) {
636 record.mWifiDisplayScanRequested = false;
637 if (--mWifiDisplayScanRequestCount == 0) {
638 if (mWifiDisplayAdapter != null) {
639 mWifiDisplayAdapter.requestStopScanLocked();
641 } else if (mWifiDisplayScanRequestCount < 0) {
642 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
643 + mWifiDisplayScanRequestCount);
644 mWifiDisplayScanRequestCount = 0;
649 private void connectWifiDisplayInternal(String address) {
650 synchronized (mSyncRoot) {
651 if (mWifiDisplayAdapter != null) {
652 mWifiDisplayAdapter.requestConnectLocked(address);
657 private void pauseWifiDisplayInternal() {
658 synchronized (mSyncRoot) {
659 if (mWifiDisplayAdapter != null) {
660 mWifiDisplayAdapter.requestPauseLocked();
665 private void resumeWifiDisplayInternal() {
666 synchronized (mSyncRoot) {
667 if (mWifiDisplayAdapter != null) {
668 mWifiDisplayAdapter.requestResumeLocked();
673 private void disconnectWifiDisplayInternal() {
674 synchronized (mSyncRoot) {
675 if (mWifiDisplayAdapter != null) {
676 mWifiDisplayAdapter.requestDisconnectLocked();
681 private void renameWifiDisplayInternal(String address, String alias) {
682 synchronized (mSyncRoot) {
683 if (mWifiDisplayAdapter != null) {
684 mWifiDisplayAdapter.requestRenameLocked(address, alias);
689 private void forgetWifiDisplayInternal(String address) {
690 synchronized (mSyncRoot) {
691 if (mWifiDisplayAdapter != null) {
692 mWifiDisplayAdapter.requestForgetLocked(address);
697 private WifiDisplayStatus getWifiDisplayStatusInternal() {
698 synchronized (mSyncRoot) {
699 if (mWifiDisplayAdapter != null) {
700 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
702 return new WifiDisplayStatus();
706 private void requestColorModeInternal(int displayId, int colorMode) {
707 synchronized (mSyncRoot) {
708 LogicalDisplay display = mLogicalDisplays.get(displayId);
709 if (display != null &&
710 display.getRequestedColorModeLocked() != colorMode) {
711 display.setRequestedColorModeLocked(colorMode);
712 scheduleTraversalLocked(false);
717 private void setSaturationLevelInternal(float level) {
718 if (level < 0 || level > 1) {
719 throw new IllegalArgumentException("Saturation level must be between 0 and 1");
721 float[] matrix = (level == 1.0f ? null : computeSaturationMatrix(level));
722 DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
723 dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION, matrix);
726 private static float[] computeSaturationMatrix(float saturation) {
727 float desaturation = 1.0f - saturation;
728 float[] luminance = {0.231f * desaturation, 0.715f * desaturation, 0.072f * desaturation};
730 luminance[0] + saturation, luminance[0], luminance[0], 0,
731 luminance[1], luminance[1] + saturation, luminance[1], 0,
732 luminance[2], luminance[2], luminance[2] + saturation, 0,
738 private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
739 IMediaProjection projection, int callingUid, String packageName, String name, int width,
740 int height, int densityDpi, Surface surface, int flags, String uniqueId) {
741 synchronized (mSyncRoot) {
742 if (mVirtualDisplayAdapter == null) {
743 Slog.w(TAG, "Rejecting request to create private virtual display "
744 + "because the virtual display adapter is not available.");
748 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
749 callback, projection, callingUid, packageName, name, width, height, densityDpi,
750 surface, flags, uniqueId);
751 if (device == null) {
755 handleDisplayDeviceAddedLocked(device);
756 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
757 if (display != null) {
758 return display.getDisplayIdLocked();
761 // Something weird happened and the logical display was not created.
762 Slog.w(TAG, "Rejecting request to create virtual display "
763 + "because the logical display was not created.");
764 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
765 handleDisplayDeviceRemovedLocked(device);
770 private void resizeVirtualDisplayInternal(IBinder appToken,
771 int width, int height, int densityDpi) {
772 synchronized (mSyncRoot) {
773 if (mVirtualDisplayAdapter == null) {
777 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
781 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
782 synchronized (mSyncRoot) {
783 if (mVirtualDisplayAdapter == null) {
787 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
791 private void releaseVirtualDisplayInternal(IBinder appToken) {
792 synchronized (mSyncRoot) {
793 if (mVirtualDisplayAdapter == null) {
797 DisplayDevice device =
798 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
799 if (device != null) {
800 handleDisplayDeviceRemovedLocked(device);
805 private void registerDefaultDisplayAdapters() {
806 // Register default display adapters.
807 synchronized (mSyncRoot) {
808 // main display adapter
809 registerDisplayAdapterLocked(new LocalDisplayAdapter(
810 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
812 // Standalone VR devices rely on a virtual display as their primary display for
813 // 2D UI. We register virtual display adapter along side the main display adapter
814 // here so that it is ready by the time the system sends the home Intent for
815 // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
816 // the virtual display inside VR before any VR-specific apps even run.
817 mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
818 mHandler, mDisplayAdapterListener);
819 if (mVirtualDisplayAdapter != null) {
820 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
825 private void registerAdditionalDisplayAdapters() {
826 synchronized (mSyncRoot) {
827 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
828 registerOverlayDisplayAdapterLocked();
829 registerWifiDisplayAdapterLocked();
834 private void registerOverlayDisplayAdapterLocked() {
835 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
836 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
839 private void registerWifiDisplayAdapterLocked() {
840 if (mContext.getResources().getBoolean(
841 com.android.internal.R.bool.config_enableWifiDisplay)
842 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
843 mWifiDisplayAdapter = new WifiDisplayAdapter(
844 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
845 mPersistentDataStore);
846 registerDisplayAdapterLocked(mWifiDisplayAdapter);
850 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
851 // In safe mode, we disable non-essential display adapters to give the user
852 // an opportunity to fix broken settings or other problems that might affect
854 // In only-core mode, we disable non-essential display adapters to minimize
855 // the number of dependencies that are started while in this mode and to
856 // prevent problems that might occur due to the device being encrypted.
857 return !mSafeMode && !mOnlyCore;
860 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
861 mDisplayAdapters.add(adapter);
862 adapter.registerLocked();
865 private void handleDisplayDeviceAdded(DisplayDevice device) {
866 synchronized (mSyncRoot) {
867 handleDisplayDeviceAddedLocked(device);
871 private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
872 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
873 if (mDisplayDevices.contains(device)) {
874 Slog.w(TAG, "Attempted to add already added display device: " + info);
878 Slog.i(TAG, "Display device added: " + info);
879 device.mDebugLastLoggedDeviceInfo = info;
881 mDisplayDevices.add(device);
882 LogicalDisplay display = addLogicalDisplayLocked(device);
883 Runnable work = updateDisplayStateLocked(device);
887 scheduleTraversalLocked(false);
890 private void handleDisplayDeviceChanged(DisplayDevice device) {
891 synchronized (mSyncRoot) {
892 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
893 if (!mDisplayDevices.contains(device)) {
894 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
898 int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
899 if (diff == DisplayDeviceInfo.DIFF_STATE) {
900 Slog.i(TAG, "Display device changed state: \"" + info.name
901 + "\", " + Display.stateToString(info.state));
902 } else if (diff != 0) {
903 Slog.i(TAG, "Display device changed: " + info);
905 if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
907 mPersistentDataStore.setColorMode(device, info.colorMode);
909 mPersistentDataStore.saveIfNeeded();
912 device.mDebugLastLoggedDeviceInfo = info;
914 device.applyPendingDisplayDeviceInfoChangesLocked();
915 if (updateLogicalDisplaysLocked()) {
916 scheduleTraversalLocked(false);
921 private void handleDisplayDeviceRemoved(DisplayDevice device) {
922 synchronized (mSyncRoot) {
923 handleDisplayDeviceRemovedLocked(device);
927 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
928 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
929 if (!mDisplayDevices.remove(device)) {
930 Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
934 Slog.i(TAG, "Display device removed: " + info);
935 device.mDebugLastLoggedDeviceInfo = info;
937 updateLogicalDisplaysLocked();
938 scheduleTraversalLocked(false);
941 private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
942 final int count = mDisplayDevices.size();
943 for (int i = 0; i < count; i++) {
944 DisplayDevice device = mDisplayDevices.get(i);
945 Runnable runnable = updateDisplayStateLocked(device);
946 if (runnable != null) {
947 workQueue.add(runnable);
952 private Runnable updateDisplayStateLocked(DisplayDevice device) {
953 // Blank or unblank the display immediately to match the state requested
954 // by the display power controller (if known).
955 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
956 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
957 return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
962 // Adds a new logical display based on the given display device.
963 // Sends notifications if needed.
964 private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
965 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
966 boolean isDefault = (deviceInfo.flags
967 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
968 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
969 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
973 if (!isDefault && mSingleDisplayDemoMode) {
974 Slog.i(TAG, "Not creating a logical display for a secondary display "
975 + " because single display demo mode is enabled: " + deviceInfo);
979 final int displayId = assignDisplayIdLocked(isDefault);
980 final int layerStack = assignLayerStackLocked(displayId);
982 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
983 display.updateLocked(mDisplayDevices);
984 if (!display.isValidLocked()) {
985 // This should never happen currently.
986 Slog.w(TAG, "Ignoring display device because the logical display "
987 + "created from it was not considered valid: " + deviceInfo);
991 configureColorModeLocked(display, device);
993 recordStableDisplayStatsIfNeededLocked(display);
996 mLogicalDisplays.put(displayId, display);
998 // Wake up waitForDefaultDisplay.
1000 mSyncRoot.notifyAll();
1003 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
1007 private int assignDisplayIdLocked(boolean isDefault) {
1008 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
1011 private int assignLayerStackLocked(int displayId) {
1012 // Currently layer stacks and display ids are the same.
1013 // This need not be the case.
1017 private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
1018 if (display.getPrimaryDisplayDeviceLocked() == device) {
1019 int colorMode = mPersistentDataStore.getColorMode(device);
1020 if (colorMode == Display.COLOR_MODE_INVALID) {
1021 if ((device.getDisplayDeviceInfoLocked().flags
1022 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1023 colorMode = mDefaultDisplayDefaultColorMode;
1025 colorMode = Display.COLOR_MODE_DEFAULT;
1028 display.setRequestedColorModeLocked(colorMode);
1032 // If we've never recorded stable device stats for this device before and they aren't
1033 // explicitly configured, go ahead and record the stable device stats now based on the status
1034 // of the default display at first boot.
1035 private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
1036 if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
1037 DisplayInfo info = d.getDisplayInfoLocked();
1038 setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
1042 private void setStableDisplaySizeLocked(int width, int height) {
1043 mStableDisplaySize = new Point(width, height);
1045 mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
1047 mPersistentDataStore.saveIfNeeded();
1052 Curve getMinimumBrightnessCurveInternal() {
1053 return mMinimumBrightnessCurve;
1056 private void setBrightnessConfigurationForUserInternal(
1057 @Nullable BrightnessConfiguration c, @UserIdInt int userId,
1058 @Nullable String packageName) {
1059 validateBrightnessConfiguration(c);
1060 final int userSerial = getUserManager().getUserSerialNumber(userId);
1061 synchronized (mSyncRoot) {
1063 mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial,
1066 mPersistentDataStore.saveIfNeeded();
1068 if (userId == mCurrentUserId) {
1069 mDisplayPowerController.setBrightnessConfiguration(c);
1075 void validateBrightnessConfiguration(BrightnessConfiguration config) {
1076 if (config == null) {
1079 if (isBrightnessConfigurationTooDark(config)) {
1080 throw new IllegalArgumentException("brightness curve is too dark");
1084 private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) {
1085 Pair<float[], float[]> curve = config.getCurve();
1086 float[] lux = curve.first;
1087 float[] nits = curve.second;
1088 for (int i = 0; i < lux.length; i++) {
1089 if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) {
1096 private void loadBrightnessConfiguration() {
1097 synchronized (mSyncRoot) {
1098 final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
1099 BrightnessConfiguration config =
1100 mPersistentDataStore.getBrightnessConfiguration(userSerial);
1101 mDisplayPowerController.setBrightnessConfiguration(config);
1105 // Updates all existing logical displays given the current set of display devices.
1106 // Removes invalid logical displays.
1107 // Sends notifications if needed.
1108 private boolean updateLogicalDisplaysLocked() {
1109 boolean changed = false;
1110 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
1111 final int displayId = mLogicalDisplays.keyAt(i);
1112 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1114 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
1115 display.updateLocked(mDisplayDevices);
1116 if (!display.isValidLocked()) {
1117 mLogicalDisplays.removeAt(i);
1118 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
1120 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
1121 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
1128 private void performTraversalLocked(SurfaceControl.Transaction t) {
1129 // Clear all viewports before configuring displays so that we can keep
1130 // track of which ones we have configured.
1131 clearViewportsLocked();
1133 // Configure each display device.
1134 final int count = mDisplayDevices.size();
1135 for (int i = 0; i < count; i++) {
1136 DisplayDevice device = mDisplayDevices.get(i);
1137 configureDisplayLocked(t, device);
1138 device.performTraversalLocked(t);
1141 // Tell the input system about these new viewports.
1142 if (mInputManagerInternal != null) {
1143 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
1147 private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
1148 float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
1149 synchronized (mSyncRoot) {
1150 LogicalDisplay display = mLogicalDisplays.get(displayId);
1151 if (display == null) {
1154 if (display.hasContentLocked() != hasContent) {
1156 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
1157 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
1160 display.setHasContentLocked(hasContent);
1161 scheduleTraversalLocked(inTraversal);
1163 if (requestedModeId == 0 && requestedRefreshRate != 0) {
1164 // Scan supported modes returned by display.getInfo() to find a mode with the same
1165 // size as the default display mode but with the specified refresh rate instead.
1166 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
1167 requestedRefreshRate);
1169 if (display.getRequestedModeIdLocked() != requestedModeId) {
1171 Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
1173 display.setRequestedModeIdLocked(requestedModeId);
1174 scheduleTraversalLocked(inTraversal);
1179 private void setDisplayOffsetsInternal(int displayId, int x, int y) {
1180 synchronized (mSyncRoot) {
1181 LogicalDisplay display = mLogicalDisplays.get(displayId);
1182 if (display == null) {
1185 if (display.getDisplayOffsetXLocked() != x
1186 || display.getDisplayOffsetYLocked() != y) {
1188 Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
1189 + x + ", " + y + ")");
1191 display.setDisplayOffsetsLocked(x, y);
1192 scheduleTraversalLocked(false);
1197 // Updates the lists of UIDs that are present on displays.
1198 private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
1199 synchronized (mSyncRoot) {
1200 mDisplayAccessUIDs.clear();
1201 for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) {
1202 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i),
1203 newDisplayAccessUIDs.valueAt(i));
1208 // Checks if provided UID's content is present on the display and UID has access to it.
1209 private boolean isUidPresentOnDisplayInternal(int uid, int displayId) {
1210 synchronized (mSyncRoot) {
1211 final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId);
1212 return displayUIDs != null && displayUIDs.indexOf(uid) != -1;
1216 private void clearViewportsLocked() {
1217 mDefaultViewport.valid = false;
1218 mExternalTouchViewport.valid = false;
1219 mVirtualTouchViewports.clear();
1222 private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
1223 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1224 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
1226 // Find the logical display that the display device is showing.
1227 // Certain displays only ever show their own content.
1228 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
1230 if (display != null && !display.hasContentLocked()) {
1231 // If the display does not have any content of its own, then
1232 // automatically mirror the default logical display contents.
1235 if (display == null) {
1236 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
1240 // Apply the logical display configuration to the display device.
1241 if (display == null) {
1242 // TODO: no logical display for the device, blank it
1243 Slog.w(TAG, "Missing logical display to use for physical display device: "
1244 + device.getDisplayDeviceInfoLocked());
1247 display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
1249 // Update the viewports if needed.
1250 if (!mDefaultViewport.valid
1251 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1252 setViewportLocked(mDefaultViewport, display, device);
1254 if (!mExternalTouchViewport.valid
1255 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
1256 setViewportLocked(mExternalTouchViewport, display, device);
1259 if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) {
1260 final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId);
1261 setViewportLocked(viewport, display, device);
1265 /** Gets the virtual device viewport or creates it if not yet created. */
1266 private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) {
1267 DisplayViewport viewport;
1268 final int count = mVirtualTouchViewports.size();
1269 for (int i = 0; i < count; i++) {
1270 viewport = mVirtualTouchViewports.get(i);
1271 if (uniqueId.equals(viewport.uniqueId)) {
1276 viewport = new DisplayViewport();
1277 viewport.uniqueId = uniqueId;
1278 mVirtualTouchViewports.add(viewport);
1282 private static void setViewportLocked(DisplayViewport viewport,
1283 LogicalDisplay display, DisplayDevice device) {
1284 viewport.valid = true;
1285 viewport.displayId = display.getDisplayIdLocked();
1286 device.populateViewportLocked(viewport);
1289 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
1290 final int count = mLogicalDisplays.size();
1291 for (int i = 0; i < count; i++) {
1292 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1293 if (display.getPrimaryDisplayDeviceLocked() == device) {
1300 private void sendDisplayEventLocked(int displayId, int event) {
1301 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
1302 mHandler.sendMessage(msg);
1305 // Requests that performTraversals be called at a
1306 // later time to apply changes to surfaces and displays.
1307 private void scheduleTraversalLocked(boolean inTraversal) {
1308 if (!mPendingTraversal && mWindowManagerInternal != null) {
1309 mPendingTraversal = true;
1311 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
1316 // Runs on Handler thread.
1317 // Delivers display event notifications to callbacks.
1318 private void deliverDisplayEvent(int displayId, int event) {
1320 Slog.d(TAG, "Delivering display event: displayId="
1321 + displayId + ", event=" + event);
1324 // Grab the lock and copy the callbacks.
1326 synchronized (mSyncRoot) {
1327 count = mCallbacks.size();
1328 mTempCallbacks.clear();
1329 for (int i = 0; i < count; i++) {
1330 mTempCallbacks.add(mCallbacks.valueAt(i));
1334 // After releasing the lock, send the notifications out.
1335 for (int i = 0; i < count; i++) {
1336 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1338 mTempCallbacks.clear();
1341 private IMediaProjectionManager getProjectionService() {
1342 if (mProjectionService == null) {
1343 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1344 mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1346 return mProjectionService;
1349 private UserManager getUserManager() {
1350 return mContext.getSystemService(UserManager.class);
1353 private void dumpInternal(PrintWriter pw) {
1354 pw.println("DISPLAY MANAGER (dumpsys display)");
1356 synchronized (mSyncRoot) {
1357 pw.println(" mOnlyCode=" + mOnlyCore);
1358 pw.println(" mSafeMode=" + mSafeMode);
1359 pw.println(" mPendingTraversal=" + mPendingTraversal);
1360 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
1361 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1362 pw.println(" mDefaultViewport=" + mDefaultViewport);
1363 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
1364 pw.println(" mVirtualTouchViewports=" + mVirtualTouchViewports);
1365 pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
1366 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
1367 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
1368 pw.println(" mStableDisplaySize=" + mStableDisplaySize);
1371 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
1372 ipw.increaseIndent();
1375 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
1376 for (DisplayAdapter adapter : mDisplayAdapters) {
1377 pw.println(" " + adapter.getName());
1378 adapter.dumpLocked(ipw);
1382 pw.println("Display Devices: size=" + mDisplayDevices.size());
1383 for (DisplayDevice device : mDisplayDevices) {
1384 pw.println(" " + device.getDisplayDeviceInfoLocked());
1385 device.dumpLocked(ipw);
1388 final int logicalDisplayCount = mLogicalDisplays.size();
1390 pw.println("Logical Displays: size=" + logicalDisplayCount);
1391 for (int i = 0; i < logicalDisplayCount; i++) {
1392 int displayId = mLogicalDisplays.keyAt(i);
1393 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1394 pw.println(" Display " + displayId + ":");
1395 display.dumpLocked(ipw);
1398 final int callbackCount = mCallbacks.size();
1400 pw.println("Callbacks: size=" + callbackCount);
1401 for (int i = 0; i < callbackCount; i++) {
1402 CallbackRecord callback = mCallbacks.valueAt(i);
1403 pw.println(" " + i + ": mPid=" + callback.mPid
1404 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
1407 if (mDisplayPowerController != null) {
1408 mDisplayPowerController.dump(pw);
1412 mPersistentDataStore.dump(pw);
1416 private static float[] getFloatArray(TypedArray array) {
1417 int length = array.length();
1418 float[] floatArray = new float[length];
1419 for (int i = 0; i < length; i++) {
1420 floatArray[i] = array.getFloat(i, Float.NaN);
1427 * This is the object that everything in the display manager locks on.
1428 * We make it an inner class within the {@link DisplayManagerService} to so that it is
1429 * clear that the object belongs to the display manager service and that it is
1430 * a unique object with a special purpose.
1432 public static final class SyncRoot {
1436 static class Injector {
1437 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
1438 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
1439 return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
1442 long getDefaultDisplayDelayTimeout() {
1443 return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
1448 DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
1449 synchronized (mSyncRoot) {
1450 LogicalDisplay display = mLogicalDisplays.get(displayId);
1451 if (display != null) {
1452 DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
1453 return displayDevice.getDisplayDeviceInfoLocked();
1459 private final class DisplayManagerHandler extends Handler {
1460 public DisplayManagerHandler(Looper looper) {
1461 super(looper, null, true /*async*/);
1465 public void handleMessage(Message msg) {
1467 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
1468 registerDefaultDisplayAdapters();
1471 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1472 registerAdditionalDisplayAdapters();
1475 case MSG_DELIVER_DISPLAY_EVENT:
1476 deliverDisplayEvent(msg.arg1, msg.arg2);
1479 case MSG_REQUEST_TRAVERSAL:
1480 mWindowManagerInternal.requestTraversalFromDisplayManager();
1483 case MSG_UPDATE_VIEWPORT: {
1484 synchronized (mSyncRoot) {
1485 mTempDefaultViewport.copyFrom(mDefaultViewport);
1486 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1487 if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
1488 mTempVirtualTouchViewports.clear();
1489 for (DisplayViewport d : mVirtualTouchViewports) {
1490 mTempVirtualTouchViewports.add(d.makeCopy());
1494 mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
1495 mTempExternalTouchViewport, mTempVirtualTouchViewports);
1499 case MSG_LOAD_BRIGHTNESS_CONFIGURATION:
1500 loadBrightnessConfiguration();
1506 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1508 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1510 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1511 handleDisplayDeviceAdded(device);
1514 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1515 handleDisplayDeviceChanged(device);
1518 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1519 handleDisplayDeviceRemoved(device);
1525 public void onTraversalRequested() {
1526 synchronized (mSyncRoot) {
1527 scheduleTraversalLocked(false);
1532 private final class CallbackRecord implements DeathRecipient {
1533 public final int mPid;
1534 private final IDisplayManagerCallback mCallback;
1536 public boolean mWifiDisplayScanRequested;
1538 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1540 mCallback = callback;
1544 public void binderDied() {
1546 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1548 onCallbackDied(this);
1551 public void notifyDisplayEventAsync(int displayId, int event) {
1553 mCallback.onDisplayEvent(displayId, event);
1554 } catch (RemoteException ex) {
1555 Slog.w(TAG, "Failed to notify process "
1556 + mPid + " that displays changed, assuming it died.", ex);
1563 final class BinderService extends IDisplayManager.Stub {
1565 * Returns information about the specified logical display.
1567 * @param displayId The logical display id.
1568 * @return The logical display info, or null if the display does not exist. The
1569 * returned object must be treated as immutable.
1571 @Override // Binder call
1572 public DisplayInfo getDisplayInfo(int displayId) {
1573 final int callingUid = Binder.getCallingUid();
1574 final long token = Binder.clearCallingIdentity();
1576 return getDisplayInfoInternal(displayId, callingUid);
1578 Binder.restoreCallingIdentity(token);
1583 * Returns the list of all display ids.
1585 @Override // Binder call
1586 public int[] getDisplayIds() {
1587 final int callingUid = Binder.getCallingUid();
1588 final long token = Binder.clearCallingIdentity();
1590 return getDisplayIdsInternal(callingUid);
1592 Binder.restoreCallingIdentity(token);
1597 * Returns the stable device display size, in pixels.
1599 @Override // Binder call
1600 public Point getStableDisplaySize() {
1601 final long token = Binder.clearCallingIdentity();
1603 return getStableDisplaySizeInternal();
1605 Binder.restoreCallingIdentity(token);
1609 @Override // Binder call
1610 public void registerCallback(IDisplayManagerCallback callback) {
1611 if (callback == null) {
1612 throw new IllegalArgumentException("listener must not be null");
1615 final int callingPid = Binder.getCallingPid();
1616 final long token = Binder.clearCallingIdentity();
1618 registerCallbackInternal(callback, callingPid);
1620 Binder.restoreCallingIdentity(token);
1624 @Override // Binder call
1625 public void startWifiDisplayScan() {
1626 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1627 "Permission required to start wifi display scans");
1629 final int callingPid = Binder.getCallingPid();
1630 final long token = Binder.clearCallingIdentity();
1632 startWifiDisplayScanInternal(callingPid);
1634 Binder.restoreCallingIdentity(token);
1638 @Override // Binder call
1639 public void stopWifiDisplayScan() {
1640 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1641 "Permission required to stop wifi display scans");
1643 final int callingPid = Binder.getCallingPid();
1644 final long token = Binder.clearCallingIdentity();
1646 stopWifiDisplayScanInternal(callingPid);
1648 Binder.restoreCallingIdentity(token);
1652 @Override // Binder call
1653 public void connectWifiDisplay(String address) {
1654 if (address == null) {
1655 throw new IllegalArgumentException("address must not be null");
1657 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1658 "Permission required to connect to a wifi display");
1660 final long token = Binder.clearCallingIdentity();
1662 connectWifiDisplayInternal(address);
1664 Binder.restoreCallingIdentity(token);
1668 @Override // Binder call
1669 public void disconnectWifiDisplay() {
1670 // This request does not require special permissions.
1671 // Any app can request disconnection from the currently active wifi display.
1672 // This exception should no longer be needed once wifi display control moves
1673 // to the media router service.
1675 final long token = Binder.clearCallingIdentity();
1677 disconnectWifiDisplayInternal();
1679 Binder.restoreCallingIdentity(token);
1683 @Override // Binder call
1684 public void renameWifiDisplay(String address, String alias) {
1685 if (address == null) {
1686 throw new IllegalArgumentException("address must not be null");
1688 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1689 "Permission required to rename to a wifi display");
1691 final long token = Binder.clearCallingIdentity();
1693 renameWifiDisplayInternal(address, alias);
1695 Binder.restoreCallingIdentity(token);
1699 @Override // Binder call
1700 public void forgetWifiDisplay(String address) {
1701 if (address == null) {
1702 throw new IllegalArgumentException("address must not be null");
1704 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1705 "Permission required to forget to a wifi display");
1707 final long token = Binder.clearCallingIdentity();
1709 forgetWifiDisplayInternal(address);
1711 Binder.restoreCallingIdentity(token);
1715 @Override // Binder call
1716 public void pauseWifiDisplay() {
1717 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1718 "Permission required to pause a wifi display session");
1720 final long token = Binder.clearCallingIdentity();
1722 pauseWifiDisplayInternal();
1724 Binder.restoreCallingIdentity(token);
1728 @Override // Binder call
1729 public void resumeWifiDisplay() {
1730 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1731 "Permission required to resume a wifi display session");
1733 final long token = Binder.clearCallingIdentity();
1735 resumeWifiDisplayInternal();
1737 Binder.restoreCallingIdentity(token);
1741 @Override // Binder call
1742 public WifiDisplayStatus getWifiDisplayStatus() {
1743 // This request does not require special permissions.
1744 // Any app can get information about available wifi displays.
1746 final long token = Binder.clearCallingIdentity();
1748 return getWifiDisplayStatusInternal();
1750 Binder.restoreCallingIdentity(token);
1754 @Override // Binder call
1755 public void requestColorMode(int displayId, int colorMode) {
1756 mContext.enforceCallingOrSelfPermission(
1757 Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
1758 "Permission required to change the display color mode");
1759 final long token = Binder.clearCallingIdentity();
1761 requestColorModeInternal(displayId, colorMode);
1763 Binder.restoreCallingIdentity(token);
1767 @Override // Binder call
1768 public void setSaturationLevel(float level) {
1769 mContext.enforceCallingOrSelfPermission(
1770 Manifest.permission.CONTROL_DISPLAY_SATURATION,
1771 "Permission required to set display saturation level");
1772 final long token = Binder.clearCallingIdentity();
1774 setSaturationLevelInternal(level);
1776 Binder.restoreCallingIdentity(token);
1780 @Override // Binder call
1781 public int createVirtualDisplay(IVirtualDisplayCallback callback,
1782 IMediaProjection projection, String packageName, String name,
1783 int width, int height, int densityDpi, Surface surface, int flags,
1785 final int callingUid = Binder.getCallingUid();
1786 if (!validatePackageName(callingUid, packageName)) {
1787 throw new SecurityException("packageName must match the calling uid");
1789 if (callback == null) {
1790 throw new IllegalArgumentException("appToken must not be null");
1792 if (TextUtils.isEmpty(name)) {
1793 throw new IllegalArgumentException("name must be non-null and non-empty");
1795 if (width <= 0 || height <= 0 || densityDpi <= 0) {
1796 throw new IllegalArgumentException("width, height, and densityDpi must be "
1797 + "greater than 0");
1799 if (surface != null && surface.isSingleBuffered()) {
1800 throw new IllegalArgumentException("Surface can't be single-buffered");
1803 if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1804 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1806 // Public displays can't be allowed to show content when locked.
1807 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
1808 throw new IllegalArgumentException(
1809 "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
1812 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1813 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1816 if (projection != null) {
1818 if (!getProjectionService().isValidMediaProjection(projection)) {
1819 throw new SecurityException("Invalid media projection");
1821 flags = projection.applyVirtualDisplayFlags(flags);
1822 } catch (RemoteException e) {
1823 throw new SecurityException("unable to validate media projection or flags");
1827 if (callingUid != Process.SYSTEM_UID &&
1828 (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1829 if (!canProjectVideo(projection)) {
1830 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1831 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1832 + "MediaProjection token in order to create a screen sharing virtual "
1836 if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1837 if (!canProjectSecureVideo(projection)) {
1838 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1839 + "or an appropriate MediaProjection token to create a "
1840 + "secure virtual display.");
1844 final long token = Binder.clearCallingIdentity();
1846 return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
1847 name, width, height, densityDpi, surface, flags, uniqueId);
1849 Binder.restoreCallingIdentity(token);
1853 @Override // Binder call
1854 public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
1855 int width, int height, int densityDpi) {
1856 final long token = Binder.clearCallingIdentity();
1858 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
1860 Binder.restoreCallingIdentity(token);
1864 @Override // Binder call
1865 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
1866 if (surface != null && surface.isSingleBuffered()) {
1867 throw new IllegalArgumentException("Surface can't be single-buffered");
1869 final long token = Binder.clearCallingIdentity();
1871 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
1873 Binder.restoreCallingIdentity(token);
1877 @Override // Binder call
1878 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
1879 final long token = Binder.clearCallingIdentity();
1881 releaseVirtualDisplayInternal(callback.asBinder());
1883 Binder.restoreCallingIdentity(token);
1887 @Override // Binder call
1888 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1889 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1891 final long token = Binder.clearCallingIdentity();
1895 Binder.restoreCallingIdentity(token);
1899 @Override // Binder call
1900 public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
1901 mContext.enforceCallingOrSelfPermission(
1902 Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
1903 "Permission to read brightness events.");
1905 final int callingUid = Binder.getCallingUid();
1906 AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
1907 final int mode = appOpsManager.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
1908 callingUid, callingPackage);
1909 final boolean hasUsageStats;
1910 if (mode == AppOpsManager.MODE_DEFAULT) {
1911 // The default behavior here is to check if PackageManager has given the app
1913 hasUsageStats = mContext.checkCallingPermission(
1914 Manifest.permission.PACKAGE_USAGE_STATS)
1915 == PackageManager.PERMISSION_GRANTED;
1917 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED;
1920 final int userId = UserHandle.getUserId(callingUid);
1921 final long token = Binder.clearCallingIdentity();
1923 synchronized (mSyncRoot) {
1924 return mDisplayPowerController.getBrightnessEvents(userId, hasUsageStats);
1927 Binder.restoreCallingIdentity(token);
1931 @Override // Binder call
1932 public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() {
1933 mContext.enforceCallingOrSelfPermission(
1934 Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS,
1935 "Permission required to to access ambient light stats.");
1936 final int callingUid = Binder.getCallingUid();
1937 final int userId = UserHandle.getUserId(callingUid);
1938 final long token = Binder.clearCallingIdentity();
1940 synchronized (mSyncRoot) {
1941 return mDisplayPowerController.getAmbientBrightnessStats(userId);
1944 Binder.restoreCallingIdentity(token);
1948 @Override // Binder call
1949 public void setBrightnessConfigurationForUser(
1950 BrightnessConfiguration c, @UserIdInt int userId, String packageName) {
1951 mContext.enforceCallingOrSelfPermission(
1952 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
1953 "Permission required to change the display's brightness configuration");
1954 if (userId != UserHandle.getCallingUserId()) {
1955 mContext.enforceCallingOrSelfPermission(
1956 Manifest.permission.INTERACT_ACROSS_USERS,
1957 "Permission required to change the display brightness"
1958 + " configuration of another user");
1960 if (packageName != null && !validatePackageName(getCallingUid(), packageName)) {
1963 final long token = Binder.clearCallingIdentity();
1965 setBrightnessConfigurationForUserInternal(c, userId, packageName);
1967 Binder.restoreCallingIdentity(token);
1971 @Override // Binder call
1972 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) {
1973 mContext.enforceCallingOrSelfPermission(
1974 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
1975 "Permission required to read the display's brightness configuration");
1976 if (userId != UserHandle.getCallingUserId()) {
1977 mContext.enforceCallingOrSelfPermission(
1978 Manifest.permission.INTERACT_ACROSS_USERS,
1979 "Permission required to read the display brightness"
1980 + " configuration of another user");
1982 final long token = Binder.clearCallingIdentity();
1984 final int userSerial = getUserManager().getUserSerialNumber(userId);
1985 synchronized (mSyncRoot) {
1986 BrightnessConfiguration config =
1987 mPersistentDataStore.getBrightnessConfiguration(userSerial);
1988 if (config == null) {
1989 config = mDisplayPowerController.getDefaultBrightnessConfiguration();
1994 Binder.restoreCallingIdentity(token);
1998 @Override // Binder call
1999 public BrightnessConfiguration getDefaultBrightnessConfiguration() {
2000 mContext.enforceCallingOrSelfPermission(
2001 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS,
2002 "Permission required to read the display's default brightness configuration");
2003 final long token = Binder.clearCallingIdentity();
2005 synchronized (mSyncRoot) {
2006 return mDisplayPowerController.getDefaultBrightnessConfiguration();
2009 Binder.restoreCallingIdentity(token);
2013 @Override // Binder call
2014 public void setTemporaryBrightness(int brightness) {
2015 mContext.enforceCallingOrSelfPermission(
2016 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2017 "Permission required to set the display's brightness");
2018 final long token = Binder.clearCallingIdentity();
2020 synchronized (mSyncRoot) {
2021 mDisplayPowerController.setTemporaryBrightness(brightness);
2024 Binder.restoreCallingIdentity(token);
2028 @Override // Binder call
2029 public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
2030 mContext.enforceCallingOrSelfPermission(
2031 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
2032 "Permission required to set the display's auto brightness adjustment");
2033 final long token = Binder.clearCallingIdentity();
2035 synchronized (mSyncRoot) {
2036 mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment);
2039 Binder.restoreCallingIdentity(token);
2043 @Override // Binder call
2044 public void onShellCommand(FileDescriptor in, FileDescriptor out,
2045 FileDescriptor err, String[] args, ShellCallback callback,
2046 ResultReceiver resultReceiver) {
2047 final long token = Binder.clearCallingIdentity();
2049 DisplayManagerShellCommand command = new DisplayManagerShellCommand(this);
2050 command.exec(this, in, out, err, args, callback, resultReceiver);
2052 Binder.restoreCallingIdentity(token);
2056 @Override // Binder call
2057 public Curve getMinimumBrightnessCurve() {
2058 final long token = Binder.clearCallingIdentity();
2060 return getMinimumBrightnessCurveInternal();
2062 Binder.restoreCallingIdentity(token);
2066 void setBrightness(int brightness) {
2067 Settings.System.putIntForUser(mContext.getContentResolver(),
2068 Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
2071 void resetBrightnessConfiguration() {
2072 setBrightnessConfigurationForUserInternal(null, mContext.getUserId(),
2073 mContext.getPackageName());
2076 private boolean validatePackageName(int uid, String packageName) {
2077 if (packageName != null) {
2078 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
2079 if (packageNames != null) {
2080 for (String n : packageNames) {
2081 if (n.equals(packageName)) {
2090 private boolean canProjectVideo(IMediaProjection projection) {
2091 if (projection != null) {
2093 if (projection.canProjectVideo()) {
2096 } catch (RemoteException e) {
2097 Slog.e(TAG, "Unable to query projection service for permissions", e);
2100 if (mContext.checkCallingPermission(
2101 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
2102 == PackageManager.PERMISSION_GRANTED) {
2105 return canProjectSecureVideo(projection);
2108 private boolean canProjectSecureVideo(IMediaProjection projection) {
2109 if (projection != null) {
2111 if (projection.canProjectSecureVideo()){
2114 } catch (RemoteException e) {
2115 Slog.e(TAG, "Unable to query projection service for permissions", e);
2118 return mContext.checkCallingPermission(
2119 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
2120 == PackageManager.PERMISSION_GRANTED;
2124 private final class LocalService extends DisplayManagerInternal {
2126 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
2127 SensorManager sensorManager) {
2128 synchronized (mSyncRoot) {
2129 DisplayBlanker blanker = new DisplayBlanker() {
2131 public void requestDisplayState(int state, int brightness) {
2132 // The order of operations is important for legacy reasons.
2133 if (state == Display.STATE_OFF) {
2134 requestGlobalDisplayStateInternal(state, brightness);
2137 callbacks.onDisplayStateChange(state);
2139 if (state != Display.STATE_OFF) {
2140 requestGlobalDisplayStateInternal(state, brightness);
2144 mDisplayPowerController = new DisplayPowerController(
2145 mContext, callbacks, handler, sensorManager, blanker);
2148 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
2152 public boolean requestPowerState(DisplayPowerRequest request,
2153 boolean waitForNegativeProximity) {
2154 synchronized (mSyncRoot) {
2155 return mDisplayPowerController.requestPowerState(request,
2156 waitForNegativeProximity);
2161 public boolean isProximitySensorAvailable() {
2162 synchronized (mSyncRoot) {
2163 return mDisplayPowerController.isProximitySensorAvailable();
2168 public DisplayInfo getDisplayInfo(int displayId) {
2169 return getDisplayInfoInternal(displayId, Process.myUid());
2173 public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
2174 if (listener == null) {
2175 throw new IllegalArgumentException("listener must not be null");
2178 registerDisplayTransactionListenerInternal(listener);
2182 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
2183 if (listener == null) {
2184 throw new IllegalArgumentException("listener must not be null");
2187 unregisterDisplayTransactionListenerInternal(listener);
2191 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
2192 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
2196 public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
2197 getNonOverrideDisplayInfoInternal(displayId, outInfo);
2201 public void performTraversal(SurfaceControl.Transaction t) {
2202 performTraversalInternal(t);
2206 public void setDisplayProperties(int displayId, boolean hasContent,
2207 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
2208 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
2209 requestedMode, inTraversal);
2213 public void setDisplayOffsets(int displayId, int x, int y) {
2214 setDisplayOffsetsInternal(displayId, x, y);
2218 public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
2219 setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
2223 public boolean isUidPresentOnDisplay(int uid, int displayId) {
2224 return isUidPresentOnDisplayInternal(uid, displayId);
2228 public void persistBrightnessTrackerState() {
2229 synchronized (mSyncRoot) {
2230 mDisplayPowerController.persistBrightnessTrackerState();
2235 public void onOverlayChanged() {
2236 synchronized (mSyncRoot) {
2237 for (int i = 0; i < mDisplayDevices.size(); i++) {
2238 mDisplayDevices.get(i).onOverlayChangedLocked();