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.content.Context;
33 import android.content.pm.PackageManager;
34 import android.content.res.Resources;
35 import android.graphics.Point;
36 import android.hardware.SensorManager;
37 import android.hardware.display.DisplayManagerGlobal;
38 import android.hardware.display.DisplayManagerInternal;
39 import android.hardware.display.DisplayViewport;
40 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
41 import android.hardware.display.IDisplayManager;
42 import android.hardware.display.IDisplayManagerCallback;
43 import android.hardware.display.IVirtualDisplayCallback;
44 import android.hardware.display.WifiDisplayStatus;
45 import android.hardware.input.InputManagerInternal;
46 import android.media.projection.IMediaProjection;
47 import android.media.projection.IMediaProjectionManager;
48 import android.os.Binder;
49 import android.os.Handler;
50 import android.os.IBinder;
51 import android.os.IBinder.DeathRecipient;
52 import android.os.Looper;
53 import android.os.Message;
54 import android.os.PowerManager;
55 import android.os.Process;
56 import android.os.RemoteException;
57 import android.os.ServiceManager;
58 import android.os.SystemClock;
59 import android.os.SystemProperties;
60 import android.os.Trace;
61 import android.text.TextUtils;
62 import android.util.IntArray;
63 import android.util.Slog;
64 import android.util.SparseArray;
65 import android.view.Display;
66 import android.view.DisplayInfo;
67 import android.view.Surface;
68 import android.view.WindowManagerInternal;
70 import com.android.server.AnimationThread;
71 import com.android.server.DisplayThread;
72 import com.android.server.LocalServices;
73 import com.android.server.SystemService;
74 import com.android.server.UiThread;
76 import java.io.FileDescriptor;
77 import java.io.PrintWriter;
78 import java.util.ArrayList;
79 import java.util.Arrays;
80 import java.util.List;
81 import java.util.concurrent.CopyOnWriteArrayList;
84 * Manages attached displays.
86 * The {@link DisplayManagerService} manages the global lifecycle of displays,
87 * decides how to configure logical displays based on the physical display devices currently
88 * attached, sends notifications to the system and to applications when the state
91 * The display manager service relies on a collection of {@link DisplayAdapter} components,
92 * for discovering and configuring physical display devices attached to the system.
93 * There are separate display adapters for each manner that devices are attached:
94 * one display adapter for built-in local displays, one for simulated non-functional
95 * displays when the system is headless, one for simulated overlay displays used for
96 * development, one for wifi displays, etc.
98 * Display adapters are only weakly coupled to the display manager service.
99 * Display adapters communicate changes in display device state to the display manager
100 * service asynchronously via a {@link DisplayAdapter.Listener} registered
101 * by the display manager service. This separation of concerns is important for
102 * two main reasons. First, it neatly encapsulates the responsibilities of these
103 * two classes: display adapters handle individual display devices whereas
104 * the display manager service handles the global state. Second, it eliminates
105 * the potential for deadlocks resulting from asynchronous display device discovery.
108 * <h3>Synchronization</h3>
110 * Because the display manager may be accessed by multiple threads, the synchronization
111 * story gets a little complicated. In particular, the window manager may call into
112 * the display manager while holding a surface transaction with the expectation that
113 * it can apply changes immediately. Unfortunately, that means we can't just do
114 * everything asynchronously (*grump*).
116 * To make this work, all of the objects that belong to the display manager must
117 * use the same lock. We call this lock the synchronization root and it has a unique
118 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are
119 * named with the "Locked" suffix.
121 * Where things get tricky is that the display manager is not allowed to make
122 * any potentially reentrant calls, especially into the window manager. We generally
123 * avoid this by making all potentially reentrant out-calls asynchronous.
126 public final class DisplayManagerService extends SystemService {
127 private static final String TAG = "DisplayManagerService";
128 private static final boolean DEBUG = false;
130 // When this system property is set to 0, WFD is forcibly disabled on boot.
131 // When this system property is set to 1, WFD is forcibly enabled on boot.
132 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
133 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
135 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
137 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
138 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
139 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
140 private static final int MSG_REQUEST_TRAVERSAL = 4;
141 private static final int MSG_UPDATE_VIEWPORT = 5;
143 private final Context mContext;
144 private final DisplayManagerHandler mHandler;
145 private final Handler mUiHandler;
146 private final DisplayAdapterListener mDisplayAdapterListener;
147 private WindowManagerInternal mWindowManagerInternal;
148 private InputManagerInternal mInputManagerInternal;
149 private IMediaProjectionManager mProjectionService;
151 // The synchronization root for the display manager.
152 // This lock guards most of the display manager's state.
153 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
154 // into WindowManagerService methods that require mWindowMap while holding this unless you are
155 // very very sure that no deadlock can occur.
156 private final SyncRoot mSyncRoot = new SyncRoot();
158 // True if in safe mode.
159 // This option may disable certain display adapters.
160 public boolean mSafeMode;
162 // True if we are in a special boot mode where only core applications and
163 // services should be started. This option may disable certain display adapters.
164 public boolean mOnlyCore;
166 // True if the display manager service should pretend there is only one display
167 // and only tell applications about the existence of the default logical display.
168 // The display manager can still mirror content to secondary displays but applications
169 // cannot present unique content on those displays.
170 // Used for demonstration purposes only.
171 private final boolean mSingleDisplayDemoMode;
173 // All callback records indexed by calling process id.
174 public final SparseArray<CallbackRecord> mCallbacks =
175 new SparseArray<CallbackRecord>();
177 // List of all currently registered display adapters.
178 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
180 // List of all currently connected display devices.
181 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
183 // List of all logical displays indexed by logical display id.
184 private final SparseArray<LogicalDisplay> mLogicalDisplays =
185 new SparseArray<LogicalDisplay>();
186 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
188 // List of all display transaction listeners.
189 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
190 new CopyOnWriteArrayList<DisplayTransactionListener>();
192 // Display power controller.
193 private DisplayPowerController mDisplayPowerController;
195 // The overall display state, independent of changes that might influence one
196 // display or another in particular.
197 private int mGlobalDisplayState = Display.STATE_ON;
199 // The overall display brightness.
200 // For now, this only applies to the built-in display but we may split it up eventually.
201 private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
203 // Set to true when there are pending display changes that have yet to be applied
204 // to the surface flinger state.
205 private boolean mPendingTraversal;
207 // The Wifi display adapter, or null if not registered.
208 private WifiDisplayAdapter mWifiDisplayAdapter;
210 // The number of active wifi display scan requests.
211 private int mWifiDisplayScanRequestCount;
213 // The virtual display adapter, or null if not registered.
214 private VirtualDisplayAdapter mVirtualDisplayAdapter;
216 // The stable device screen height and width. These are not tied to a specific display, even
217 // the default display, because they need to be stable over the course of the device's entire
218 // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like
220 private Point mStableDisplaySize = new Point();
222 // Viewports of the default display and the display that should receive touch
223 // input from an external source. Used by the input system.
224 private final DisplayViewport mDefaultViewport = new DisplayViewport();
225 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
226 private final ArrayList<DisplayViewport> mVirtualTouchViewports = new ArrayList<>();
228 // Persistent data store for all internal settings maintained by the display manager service.
229 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
231 // Temporary callback list, used when sending display events to applications.
232 // May be used outside of the lock but only on the handler thread.
233 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
235 // Temporary display info, used for comparing display configurations.
236 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
238 // Temporary viewports, used when sending new viewport information to the
239 // input system. May be used outside of the lock but only on the handler thread.
240 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
241 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
242 private final ArrayList<DisplayViewport> mTempVirtualTouchViewports = new ArrayList<>();
244 // The default color mode for default displays. Overrides the usual
245 // Display.Display.COLOR_MODE_DEFAULT for displays with the
246 // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set.
247 private final int mDefaultDisplayDefaultColorMode;
249 // Temporary list of deferred work to perform when setting the display state.
250 // Only used by requestDisplayState. The field is self-synchronized and only
251 // intended for use inside of the requestGlobalDisplayStateInternal function.
252 private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
254 // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs.
255 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
257 private final Injector mInjector;
259 public DisplayManagerService(Context context) {
260 this(context, new Injector());
264 DisplayManagerService(Context context, Injector injector) {
266 mInjector = injector;
268 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
269 mUiHandler = UiThread.getHandler();
270 mDisplayAdapterListener = new DisplayAdapterListener();
271 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
272 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
273 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
275 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
276 mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
279 public void setupSchedulerPolicies() {
280 // android.display and android.anim is critical to user experience and we should make sure
281 // it is not in the default foregroup groups, add it to top-app to make sure it uses all the
282 // cores and scheduling settings for top-app when it runs.
283 Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
284 Process.THREAD_GROUP_TOP_APP);
285 Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
286 Process.THREAD_GROUP_TOP_APP);
290 public void onStart() {
291 // We need to pre-load the persistent data store so it's ready before the default display
292 // adapter is up so that we have it's configuration. We could load it lazily, but since
293 // we're going to have to read it in eventually we may as well do it here rather than after
294 // we've waited for the display to register itself with us.
295 synchronized(mSyncRoot) {
296 mPersistentDataStore.loadIfNeeded();
297 loadStableDisplayValuesLocked();
299 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
301 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
302 true /*allowIsolated*/);
303 publishLocalService(DisplayManagerInternal.class, new LocalService());
304 publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
308 public void onBootPhase(int phase) {
309 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
310 synchronized (mSyncRoot) {
311 long timeout = SystemClock.uptimeMillis()
312 + mInjector.getDefaultDisplayDelayTimeout();
313 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
314 mVirtualDisplayAdapter == null) {
315 long delay = timeout - SystemClock.uptimeMillis();
317 throw new RuntimeException("Timeout waiting for default display "
318 + "to be initialized. DefaultDisplay="
319 + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
320 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
323 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
326 mSyncRoot.wait(delay);
327 } catch (InterruptedException ex) {
334 // TODO: Use dependencies or a boot phase
335 public void windowManagerAndInputReady() {
336 synchronized (mSyncRoot) {
337 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
338 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
339 scheduleTraversalLocked(false);
344 * Called when the system is ready to go.
346 public void systemReady(boolean safeMode, boolean onlyCore) {
347 synchronized (mSyncRoot) {
348 mSafeMode = safeMode;
349 mOnlyCore = onlyCore;
352 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
356 Handler getDisplayHandler() {
360 private void loadStableDisplayValuesLocked() {
361 final Point size = mPersistentDataStore.getStableDisplaySize();
362 if (size.x > 0 && size.y > 0) {
363 // Just set these values directly so we don't write the display persistent data again
365 mStableDisplaySize.set(size.x, size.y);
367 final Resources res = mContext.getResources();
368 final int width = res.getInteger(
369 com.android.internal.R.integer.config_stableDeviceDisplayWidth);
370 final int height = res.getInteger(
371 com.android.internal.R.integer.config_stableDeviceDisplayHeight);
372 if (width > 0 && height > 0) {
373 setStableDisplaySizeLocked(width, height);
378 private Point getStableDisplaySizeInternal() {
379 Point r = new Point();
380 synchronized (mSyncRoot) {
381 if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) {
382 r.set(mStableDisplaySize.x, mStableDisplaySize.y);
388 private void registerDisplayTransactionListenerInternal(
389 DisplayTransactionListener listener) {
390 // List is self-synchronized copy-on-write.
391 mDisplayTransactionListeners.add(listener);
394 private void unregisterDisplayTransactionListenerInternal(
395 DisplayTransactionListener listener) {
396 // List is self-synchronized copy-on-write.
397 mDisplayTransactionListeners.remove(listener);
400 private void setDisplayInfoOverrideFromWindowManagerInternal(
401 int displayId, DisplayInfo info) {
402 synchronized (mSyncRoot) {
403 LogicalDisplay display = mLogicalDisplays.get(displayId);
404 if (display != null) {
405 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
406 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
407 scheduleTraversalLocked(false);
414 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
416 private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) {
417 synchronized (mSyncRoot) {
418 final LogicalDisplay display = mLogicalDisplays.get(displayId);
419 if (display != null) {
420 display.getNonOverrideDisplayInfoLocked(outInfo);
426 void performTraversalInTransactionFromWindowManagerInternal() {
427 synchronized (mSyncRoot) {
428 if (!mPendingTraversal) {
431 mPendingTraversal = false;
433 performTraversalInTransactionLocked();
436 // List is self-synchronized copy-on-write.
437 for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
438 listener.onDisplayTransaction();
442 private void requestGlobalDisplayStateInternal(int state, int brightness) {
443 if (state == Display.STATE_UNKNOWN) {
444 state = Display.STATE_ON;
446 if (state == Display.STATE_OFF) {
447 brightness = PowerManager.BRIGHTNESS_OFF;
448 } else if (brightness < 0) {
449 brightness = PowerManager.BRIGHTNESS_DEFAULT;
450 } else if (brightness > PowerManager.BRIGHTNESS_ON) {
451 brightness = PowerManager.BRIGHTNESS_ON;
454 synchronized (mTempDisplayStateWorkQueue) {
456 // Update the display state within the lock.
457 // Note that we do not need to schedule traversals here although it
458 // may happen as a side-effect of displays changing state.
459 synchronized (mSyncRoot) {
460 if (mGlobalDisplayState == state
461 && mGlobalDisplayBrightness == brightness) {
465 Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
466 + Display.stateToString(state)
467 + ", brightness=" + brightness + ")");
468 mGlobalDisplayState = state;
469 mGlobalDisplayBrightness = brightness;
470 if (state != Display.STATE_OFF) {
471 applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
475 // Setting the display power state can take hundreds of milliseconds
476 // to complete so we defer the most expensive part of the work until
477 // after we have exited the critical section to avoid blocking other
478 // threads for a long time.
479 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
480 mTempDisplayStateWorkQueue.get(i).run();
482 Trace.traceEnd(Trace.TRACE_TAG_POWER);
484 mTempDisplayStateWorkQueue.clear();
489 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
490 synchronized (mSyncRoot) {
491 LogicalDisplay display = mLogicalDisplays.get(displayId);
492 if (display != null) {
493 DisplayInfo info = display.getDisplayInfoLocked();
494 if (info.hasAccess(callingUid)
495 || isUidPresentOnDisplayInternal(callingUid, displayId)) {
503 private int[] getDisplayIdsInternal(int callingUid) {
504 synchronized (mSyncRoot) {
505 final int count = mLogicalDisplays.size();
506 int[] displayIds = new int[count];
508 for (int i = 0; i < count; i++) {
509 LogicalDisplay display = mLogicalDisplays.valueAt(i);
510 DisplayInfo info = display.getDisplayInfoLocked();
511 if (info.hasAccess(callingUid)) {
512 displayIds[n++] = mLogicalDisplays.keyAt(i);
516 displayIds = Arrays.copyOfRange(displayIds, 0, n);
522 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
523 synchronized (mSyncRoot) {
524 if (mCallbacks.get(callingPid) != null) {
525 throw new SecurityException("The calling process has already "
526 + "registered an IDisplayManagerCallback.");
529 CallbackRecord record = new CallbackRecord(callingPid, callback);
531 IBinder binder = callback.asBinder();
532 binder.linkToDeath(record, 0);
533 } catch (RemoteException ex) {
535 throw new RuntimeException(ex);
538 mCallbacks.put(callingPid, record);
542 private void onCallbackDied(CallbackRecord record) {
543 synchronized (mSyncRoot) {
544 mCallbacks.remove(record.mPid);
545 stopWifiDisplayScanLocked(record);
549 private void startWifiDisplayScanInternal(int callingPid) {
550 synchronized (mSyncRoot) {
551 CallbackRecord record = mCallbacks.get(callingPid);
552 if (record == null) {
553 throw new IllegalStateException("The calling process has not "
554 + "registered an IDisplayManagerCallback.");
556 startWifiDisplayScanLocked(record);
560 private void startWifiDisplayScanLocked(CallbackRecord record) {
561 if (!record.mWifiDisplayScanRequested) {
562 record.mWifiDisplayScanRequested = true;
563 if (mWifiDisplayScanRequestCount++ == 0) {
564 if (mWifiDisplayAdapter != null) {
565 mWifiDisplayAdapter.requestStartScanLocked();
571 private void stopWifiDisplayScanInternal(int callingPid) {
572 synchronized (mSyncRoot) {
573 CallbackRecord record = mCallbacks.get(callingPid);
574 if (record == null) {
575 throw new IllegalStateException("The calling process has not "
576 + "registered an IDisplayManagerCallback.");
578 stopWifiDisplayScanLocked(record);
582 private void stopWifiDisplayScanLocked(CallbackRecord record) {
583 if (record.mWifiDisplayScanRequested) {
584 record.mWifiDisplayScanRequested = false;
585 if (--mWifiDisplayScanRequestCount == 0) {
586 if (mWifiDisplayAdapter != null) {
587 mWifiDisplayAdapter.requestStopScanLocked();
589 } else if (mWifiDisplayScanRequestCount < 0) {
590 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
591 + mWifiDisplayScanRequestCount);
592 mWifiDisplayScanRequestCount = 0;
597 private void connectWifiDisplayInternal(String address) {
598 synchronized (mSyncRoot) {
599 if (mWifiDisplayAdapter != null) {
600 mWifiDisplayAdapter.requestConnectLocked(address);
605 private void pauseWifiDisplayInternal() {
606 synchronized (mSyncRoot) {
607 if (mWifiDisplayAdapter != null) {
608 mWifiDisplayAdapter.requestPauseLocked();
613 private void resumeWifiDisplayInternal() {
614 synchronized (mSyncRoot) {
615 if (mWifiDisplayAdapter != null) {
616 mWifiDisplayAdapter.requestResumeLocked();
621 private void disconnectWifiDisplayInternal() {
622 synchronized (mSyncRoot) {
623 if (mWifiDisplayAdapter != null) {
624 mWifiDisplayAdapter.requestDisconnectLocked();
629 private void renameWifiDisplayInternal(String address, String alias) {
630 synchronized (mSyncRoot) {
631 if (mWifiDisplayAdapter != null) {
632 mWifiDisplayAdapter.requestRenameLocked(address, alias);
637 private void forgetWifiDisplayInternal(String address) {
638 synchronized (mSyncRoot) {
639 if (mWifiDisplayAdapter != null) {
640 mWifiDisplayAdapter.requestForgetLocked(address);
645 private WifiDisplayStatus getWifiDisplayStatusInternal() {
646 synchronized (mSyncRoot) {
647 if (mWifiDisplayAdapter != null) {
648 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
650 return new WifiDisplayStatus();
654 private void requestColorModeInternal(int displayId, int colorMode) {
655 synchronized (mSyncRoot) {
656 LogicalDisplay display = mLogicalDisplays.get(displayId);
657 if (display != null &&
658 display.getRequestedColorModeLocked() != colorMode) {
659 display.setRequestedColorModeLocked(colorMode);
660 scheduleTraversalLocked(false);
665 private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
666 IMediaProjection projection, int callingUid, String packageName, String name, int width,
667 int height, int densityDpi, Surface surface, int flags, String uniqueId) {
668 synchronized (mSyncRoot) {
669 if (mVirtualDisplayAdapter == null) {
670 Slog.w(TAG, "Rejecting request to create private virtual display "
671 + "because the virtual display adapter is not available.");
675 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
676 callback, projection, callingUid, packageName, name, width, height, densityDpi,
677 surface, flags, uniqueId);
678 if (device == null) {
682 handleDisplayDeviceAddedLocked(device);
683 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
684 if (display != null) {
685 return display.getDisplayIdLocked();
688 // Something weird happened and the logical display was not created.
689 Slog.w(TAG, "Rejecting request to create virtual display "
690 + "because the logical display was not created.");
691 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
692 handleDisplayDeviceRemovedLocked(device);
697 private void resizeVirtualDisplayInternal(IBinder appToken,
698 int width, int height, int densityDpi) {
699 synchronized (mSyncRoot) {
700 if (mVirtualDisplayAdapter == null) {
704 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
708 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
709 synchronized (mSyncRoot) {
710 if (mVirtualDisplayAdapter == null) {
714 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
718 private void releaseVirtualDisplayInternal(IBinder appToken) {
719 synchronized (mSyncRoot) {
720 if (mVirtualDisplayAdapter == null) {
724 DisplayDevice device =
725 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
726 if (device != null) {
727 handleDisplayDeviceRemovedLocked(device);
732 private void registerDefaultDisplayAdapters() {
733 // Register default display adapters.
734 synchronized (mSyncRoot) {
735 // main display adapter
736 registerDisplayAdapterLocked(new LocalDisplayAdapter(
737 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
739 // Standalone VR devices rely on a virtual display as their primary display for
740 // 2D UI. We register virtual display adapter along side the main display adapter
741 // here so that it is ready by the time the system sends the home Intent for
742 // early apps like SetupWizard/Launcher. In particular, SUW is displayed using
743 // the virtual display inside VR before any VR-specific apps even run.
744 mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
745 mHandler, mDisplayAdapterListener);
746 if (mVirtualDisplayAdapter != null) {
747 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
752 private void registerAdditionalDisplayAdapters() {
753 synchronized (mSyncRoot) {
754 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
755 registerOverlayDisplayAdapterLocked();
756 registerWifiDisplayAdapterLocked();
761 private void registerOverlayDisplayAdapterLocked() {
762 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
763 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
766 private void registerWifiDisplayAdapterLocked() {
767 if (mContext.getResources().getBoolean(
768 com.android.internal.R.bool.config_enableWifiDisplay)
769 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
770 mWifiDisplayAdapter = new WifiDisplayAdapter(
771 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
772 mPersistentDataStore);
773 registerDisplayAdapterLocked(mWifiDisplayAdapter);
777 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
778 // In safe mode, we disable non-essential display adapters to give the user
779 // an opportunity to fix broken settings or other problems that might affect
781 // In only-core mode, we disable non-essential display adapters to minimize
782 // the number of dependencies that are started while in this mode and to
783 // prevent problems that might occur due to the device being encrypted.
784 return !mSafeMode && !mOnlyCore;
787 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
788 mDisplayAdapters.add(adapter);
789 adapter.registerLocked();
792 private void handleDisplayDeviceAdded(DisplayDevice device) {
793 synchronized (mSyncRoot) {
794 handleDisplayDeviceAddedLocked(device);
798 private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
799 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
800 if (mDisplayDevices.contains(device)) {
801 Slog.w(TAG, "Attempted to add already added display device: " + info);
805 Slog.i(TAG, "Display device added: " + info);
806 device.mDebugLastLoggedDeviceInfo = info;
808 mDisplayDevices.add(device);
809 LogicalDisplay display = addLogicalDisplayLocked(device);
810 Runnable work = updateDisplayStateLocked(device);
814 scheduleTraversalLocked(false);
817 private void handleDisplayDeviceChanged(DisplayDevice device) {
818 synchronized (mSyncRoot) {
819 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
820 if (!mDisplayDevices.contains(device)) {
821 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
825 int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
826 if (diff == DisplayDeviceInfo.DIFF_STATE) {
827 Slog.i(TAG, "Display device changed state: \"" + info.name
828 + "\", " + Display.stateToString(info.state));
829 } else if (diff != 0) {
830 Slog.i(TAG, "Display device changed: " + info);
832 if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
834 mPersistentDataStore.setColorMode(device, info.colorMode);
836 mPersistentDataStore.saveIfNeeded();
839 device.mDebugLastLoggedDeviceInfo = info;
841 device.applyPendingDisplayDeviceInfoChangesLocked();
842 if (updateLogicalDisplaysLocked()) {
843 scheduleTraversalLocked(false);
848 private void handleDisplayDeviceRemoved(DisplayDevice device) {
849 synchronized (mSyncRoot) {
850 handleDisplayDeviceRemovedLocked(device);
854 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
855 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
856 if (!mDisplayDevices.remove(device)) {
857 Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
861 Slog.i(TAG, "Display device removed: " + info);
862 device.mDebugLastLoggedDeviceInfo = info;
864 updateLogicalDisplaysLocked();
865 scheduleTraversalLocked(false);
868 private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
869 final int count = mDisplayDevices.size();
870 for (int i = 0; i < count; i++) {
871 DisplayDevice device = mDisplayDevices.get(i);
872 Runnable runnable = updateDisplayStateLocked(device);
873 if (runnable != null) {
874 workQueue.add(runnable);
879 private Runnable updateDisplayStateLocked(DisplayDevice device) {
880 // Blank or unblank the display immediately to match the state requested
881 // by the display power controller (if known).
882 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
883 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
884 return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
889 // Adds a new logical display based on the given display device.
890 // Sends notifications if needed.
891 private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
892 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
893 boolean isDefault = (deviceInfo.flags
894 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
895 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
896 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
900 if (!isDefault && mSingleDisplayDemoMode) {
901 Slog.i(TAG, "Not creating a logical display for a secondary display "
902 + " because single display demo mode is enabled: " + deviceInfo);
906 final int displayId = assignDisplayIdLocked(isDefault);
907 final int layerStack = assignLayerStackLocked(displayId);
909 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
910 display.updateLocked(mDisplayDevices);
911 if (!display.isValidLocked()) {
912 // This should never happen currently.
913 Slog.w(TAG, "Ignoring display device because the logical display "
914 + "created from it was not considered valid: " + deviceInfo);
918 configureColorModeLocked(display, device);
920 recordStableDisplayStatsIfNeededLocked(display);
923 mLogicalDisplays.put(displayId, display);
925 // Wake up waitForDefaultDisplay.
927 mSyncRoot.notifyAll();
930 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
934 private int assignDisplayIdLocked(boolean isDefault) {
935 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
938 private int assignLayerStackLocked(int displayId) {
939 // Currently layer stacks and display ids are the same.
940 // This need not be the case.
944 private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) {
945 if (display.getPrimaryDisplayDeviceLocked() == device) {
946 int colorMode = mPersistentDataStore.getColorMode(device);
947 if (colorMode == Display.COLOR_MODE_INVALID) {
948 if ((device.getDisplayDeviceInfoLocked().flags
949 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
950 colorMode = mDefaultDisplayDefaultColorMode;
952 colorMode = Display.COLOR_MODE_DEFAULT;
955 display.setRequestedColorModeLocked(colorMode);
959 // If we've never recorded stable device stats for this device before and they aren't
960 // explicitly configured, go ahead and record the stable device stats now based on the status
961 // of the default display at first boot.
962 private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) {
963 if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) {
964 DisplayInfo info = d.getDisplayInfoLocked();
965 setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight());
969 private void setStableDisplaySizeLocked(int width, int height) {
970 mStableDisplaySize = new Point(width, height);
972 mPersistentDataStore.setStableDisplaySize(mStableDisplaySize);
974 mPersistentDataStore.saveIfNeeded();
978 // Updates all existing logical displays given the current set of display devices.
979 // Removes invalid logical displays.
980 // Sends notifications if needed.
981 private boolean updateLogicalDisplaysLocked() {
982 boolean changed = false;
983 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
984 final int displayId = mLogicalDisplays.keyAt(i);
985 LogicalDisplay display = mLogicalDisplays.valueAt(i);
987 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
988 display.updateLocked(mDisplayDevices);
989 if (!display.isValidLocked()) {
990 mLogicalDisplays.removeAt(i);
991 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
993 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
994 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
1001 private void performTraversalInTransactionLocked() {
1002 // Clear all viewports before configuring displays so that we can keep
1003 // track of which ones we have configured.
1004 clearViewportsLocked();
1006 // Configure each display device.
1007 final int count = mDisplayDevices.size();
1008 for (int i = 0; i < count; i++) {
1009 DisplayDevice device = mDisplayDevices.get(i);
1010 configureDisplayInTransactionLocked(device);
1011 device.performTraversalInTransactionLocked();
1014 // Tell the input system about these new viewports.
1015 if (mInputManagerInternal != null) {
1016 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
1020 private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
1021 float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
1022 synchronized (mSyncRoot) {
1023 LogicalDisplay display = mLogicalDisplays.get(displayId);
1024 if (display == null) {
1027 if (display.hasContentLocked() != hasContent) {
1029 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
1030 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
1033 display.setHasContentLocked(hasContent);
1034 scheduleTraversalLocked(inTraversal);
1036 if (requestedModeId == 0 && requestedRefreshRate != 0) {
1037 // Scan supported modes returned by display.getInfo() to find a mode with the same
1038 // size as the default display mode but with the specified refresh rate instead.
1039 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
1040 requestedRefreshRate);
1042 if (display.getRequestedModeIdLocked() != requestedModeId) {
1044 Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
1046 display.setRequestedModeIdLocked(requestedModeId);
1047 scheduleTraversalLocked(inTraversal);
1052 private void setDisplayOffsetsInternal(int displayId, int x, int y) {
1053 synchronized (mSyncRoot) {
1054 LogicalDisplay display = mLogicalDisplays.get(displayId);
1055 if (display == null) {
1058 if (display.getDisplayOffsetXLocked() != x
1059 || display.getDisplayOffsetYLocked() != y) {
1061 Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
1062 + x + ", " + y + ")");
1064 display.setDisplayOffsetsLocked(x, y);
1065 scheduleTraversalLocked(false);
1070 // Updates the lists of UIDs that are present on displays.
1071 private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) {
1072 synchronized (mSyncRoot) {
1073 mDisplayAccessUIDs.clear();
1074 for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) {
1075 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i),
1076 newDisplayAccessUIDs.valueAt(i));
1081 // Checks if provided UID's content is present on the display and UID has access to it.
1082 private boolean isUidPresentOnDisplayInternal(int uid, int displayId) {
1083 synchronized (mSyncRoot) {
1084 final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId);
1085 return displayUIDs != null && displayUIDs.indexOf(uid) != -1;
1089 private void clearViewportsLocked() {
1090 mDefaultViewport.valid = false;
1091 mExternalTouchViewport.valid = false;
1092 mVirtualTouchViewports.clear();
1095 private void configureDisplayInTransactionLocked(DisplayDevice device) {
1096 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
1097 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
1099 // Find the logical display that the display device is showing.
1100 // Certain displays only ever show their own content.
1101 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
1103 if (display != null && !display.hasContentLocked()) {
1104 // If the display does not have any content of its own, then
1105 // automatically mirror the default logical display contents.
1108 if (display == null) {
1109 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
1113 // Apply the logical display configuration to the display device.
1114 if (display == null) {
1115 // TODO: no logical display for the device, blank it
1116 Slog.w(TAG, "Missing logical display to use for physical display device: "
1117 + device.getDisplayDeviceInfoLocked());
1120 display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
1122 // Update the viewports if needed.
1123 if (!mDefaultViewport.valid
1124 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
1125 setViewportLocked(mDefaultViewport, display, device);
1127 if (!mExternalTouchViewport.valid
1128 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
1129 setViewportLocked(mExternalTouchViewport, display, device);
1132 if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) {
1133 final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId);
1134 setViewportLocked(viewport, display, device);
1138 /** Gets the virtual device viewport or creates it if not yet created. */
1139 private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) {
1140 DisplayViewport viewport;
1141 final int count = mVirtualTouchViewports.size();
1142 for (int i = 0; i < count; i++) {
1143 viewport = mVirtualTouchViewports.get(i);
1144 if (uniqueId.equals(viewport.uniqueId)) {
1149 viewport = new DisplayViewport();
1150 viewport.uniqueId = uniqueId;
1151 mVirtualTouchViewports.add(viewport);
1155 private static void setViewportLocked(DisplayViewport viewport,
1156 LogicalDisplay display, DisplayDevice device) {
1157 viewport.valid = true;
1158 viewport.displayId = display.getDisplayIdLocked();
1159 device.populateViewportLocked(viewport);
1162 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
1163 final int count = mLogicalDisplays.size();
1164 for (int i = 0; i < count; i++) {
1165 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1166 if (display.getPrimaryDisplayDeviceLocked() == device) {
1173 private void sendDisplayEventLocked(int displayId, int event) {
1174 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
1175 mHandler.sendMessage(msg);
1178 // Requests that performTraversalsInTransactionFromWindowManager be called at a
1179 // later time to apply changes to surfaces and displays.
1180 private void scheduleTraversalLocked(boolean inTraversal) {
1181 if (!mPendingTraversal && mWindowManagerInternal != null) {
1182 mPendingTraversal = true;
1184 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
1189 // Runs on Handler thread.
1190 // Delivers display event notifications to callbacks.
1191 private void deliverDisplayEvent(int displayId, int event) {
1193 Slog.d(TAG, "Delivering display event: displayId="
1194 + displayId + ", event=" + event);
1197 // Grab the lock and copy the callbacks.
1199 synchronized (mSyncRoot) {
1200 count = mCallbacks.size();
1201 mTempCallbacks.clear();
1202 for (int i = 0; i < count; i++) {
1203 mTempCallbacks.add(mCallbacks.valueAt(i));
1207 // After releasing the lock, send the notifications out.
1208 for (int i = 0; i < count; i++) {
1209 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1211 mTempCallbacks.clear();
1214 private IMediaProjectionManager getProjectionService() {
1215 if (mProjectionService == null) {
1216 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1217 mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1219 return mProjectionService;
1222 private void dumpInternal(PrintWriter pw) {
1223 pw.println("DISPLAY MANAGER (dumpsys display)");
1225 synchronized (mSyncRoot) {
1226 pw.println(" mOnlyCode=" + mOnlyCore);
1227 pw.println(" mSafeMode=" + mSafeMode);
1228 pw.println(" mPendingTraversal=" + mPendingTraversal);
1229 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
1230 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1231 pw.println(" mDefaultViewport=" + mDefaultViewport);
1232 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
1233 pw.println(" mVirtualTouchViewports=" + mVirtualTouchViewports);
1234 pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode);
1235 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
1236 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
1237 pw.println(" mStableDisplaySize=" + mStableDisplaySize);
1240 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
1241 ipw.increaseIndent();
1244 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
1245 for (DisplayAdapter adapter : mDisplayAdapters) {
1246 pw.println(" " + adapter.getName());
1247 adapter.dumpLocked(ipw);
1251 pw.println("Display Devices: size=" + mDisplayDevices.size());
1252 for (DisplayDevice device : mDisplayDevices) {
1253 pw.println(" " + device.getDisplayDeviceInfoLocked());
1254 device.dumpLocked(ipw);
1257 final int logicalDisplayCount = mLogicalDisplays.size();
1259 pw.println("Logical Displays: size=" + logicalDisplayCount);
1260 for (int i = 0; i < logicalDisplayCount; i++) {
1261 int displayId = mLogicalDisplays.keyAt(i);
1262 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1263 pw.println(" Display " + displayId + ":");
1264 display.dumpLocked(ipw);
1267 final int callbackCount = mCallbacks.size();
1269 pw.println("Callbacks: size=" + callbackCount);
1270 for (int i = 0; i < callbackCount; i++) {
1271 CallbackRecord callback = mCallbacks.valueAt(i);
1272 pw.println(" " + i + ": mPid=" + callback.mPid
1273 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
1276 if (mDisplayPowerController != null) {
1277 mDisplayPowerController.dump(pw);
1281 mPersistentDataStore.dump(pw);
1286 * This is the object that everything in the display manager locks on.
1287 * We make it an inner class within the {@link DisplayManagerService} to so that it is
1288 * clear that the object belongs to the display manager service and that it is
1289 * a unique object with a special purpose.
1291 public static final class SyncRoot {
1295 static class Injector {
1296 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
1297 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
1298 return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener);
1301 long getDefaultDisplayDelayTimeout() {
1302 return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
1307 DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
1308 synchronized (mSyncRoot) {
1309 LogicalDisplay display = mLogicalDisplays.get(displayId);
1310 if (display != null) {
1311 DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
1312 return displayDevice.getDisplayDeviceInfoLocked();
1318 private final class DisplayManagerHandler extends Handler {
1319 public DisplayManagerHandler(Looper looper) {
1320 super(looper, null, true /*async*/);
1324 public void handleMessage(Message msg) {
1326 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
1327 registerDefaultDisplayAdapters();
1330 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1331 registerAdditionalDisplayAdapters();
1334 case MSG_DELIVER_DISPLAY_EVENT:
1335 deliverDisplayEvent(msg.arg1, msg.arg2);
1338 case MSG_REQUEST_TRAVERSAL:
1339 mWindowManagerInternal.requestTraversalFromDisplayManager();
1342 case MSG_UPDATE_VIEWPORT: {
1343 synchronized (mSyncRoot) {
1344 mTempDefaultViewport.copyFrom(mDefaultViewport);
1345 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1346 if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) {
1347 mTempVirtualTouchViewports.clear();
1348 for (DisplayViewport d : mVirtualTouchViewports) {
1349 mTempVirtualTouchViewports.add(d.makeCopy());
1353 mInputManagerInternal.setDisplayViewports(mTempDefaultViewport,
1354 mTempExternalTouchViewport, mTempVirtualTouchViewports);
1361 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1363 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1365 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1366 handleDisplayDeviceAdded(device);
1369 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1370 handleDisplayDeviceChanged(device);
1373 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1374 handleDisplayDeviceRemoved(device);
1380 public void onTraversalRequested() {
1381 synchronized (mSyncRoot) {
1382 scheduleTraversalLocked(false);
1387 private final class CallbackRecord implements DeathRecipient {
1388 public final int mPid;
1389 private final IDisplayManagerCallback mCallback;
1391 public boolean mWifiDisplayScanRequested;
1393 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1395 mCallback = callback;
1399 public void binderDied() {
1401 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1403 onCallbackDied(this);
1406 public void notifyDisplayEventAsync(int displayId, int event) {
1408 mCallback.onDisplayEvent(displayId, event);
1409 } catch (RemoteException ex) {
1410 Slog.w(TAG, "Failed to notify process "
1411 + mPid + " that displays changed, assuming it died.", ex);
1418 final class BinderService extends IDisplayManager.Stub {
1420 * Returns information about the specified logical display.
1422 * @param displayId The logical display id.
1423 * @return The logical display info, or null if the display does not exist. The
1424 * returned object must be treated as immutable.
1426 @Override // Binder call
1427 public DisplayInfo getDisplayInfo(int displayId) {
1428 final int callingUid = Binder.getCallingUid();
1429 final long token = Binder.clearCallingIdentity();
1431 return getDisplayInfoInternal(displayId, callingUid);
1433 Binder.restoreCallingIdentity(token);
1438 * Returns the list of all display ids.
1440 @Override // Binder call
1441 public int[] getDisplayIds() {
1442 final int callingUid = Binder.getCallingUid();
1443 final long token = Binder.clearCallingIdentity();
1445 return getDisplayIdsInternal(callingUid);
1447 Binder.restoreCallingIdentity(token);
1452 * Returns the stable device display size, in pixels.
1454 @Override // Binder call
1455 public Point getStableDisplaySize() {
1456 final long token = Binder.clearCallingIdentity();
1458 return getStableDisplaySizeInternal();
1460 Binder.restoreCallingIdentity(token);
1464 @Override // Binder call
1465 public void registerCallback(IDisplayManagerCallback callback) {
1466 if (callback == null) {
1467 throw new IllegalArgumentException("listener must not be null");
1470 final int callingPid = Binder.getCallingPid();
1471 final long token = Binder.clearCallingIdentity();
1473 registerCallbackInternal(callback, callingPid);
1475 Binder.restoreCallingIdentity(token);
1479 @Override // Binder call
1480 public void startWifiDisplayScan() {
1481 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1482 "Permission required to start wifi display scans");
1484 final int callingPid = Binder.getCallingPid();
1485 final long token = Binder.clearCallingIdentity();
1487 startWifiDisplayScanInternal(callingPid);
1489 Binder.restoreCallingIdentity(token);
1493 @Override // Binder call
1494 public void stopWifiDisplayScan() {
1495 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1496 "Permission required to stop wifi display scans");
1498 final int callingPid = Binder.getCallingPid();
1499 final long token = Binder.clearCallingIdentity();
1501 stopWifiDisplayScanInternal(callingPid);
1503 Binder.restoreCallingIdentity(token);
1507 @Override // Binder call
1508 public void connectWifiDisplay(String address) {
1509 if (address == null) {
1510 throw new IllegalArgumentException("address must not be null");
1512 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1513 "Permission required to connect to a wifi display");
1515 final long token = Binder.clearCallingIdentity();
1517 connectWifiDisplayInternal(address);
1519 Binder.restoreCallingIdentity(token);
1523 @Override // Binder call
1524 public void disconnectWifiDisplay() {
1525 // This request does not require special permissions.
1526 // Any app can request disconnection from the currently active wifi display.
1527 // This exception should no longer be needed once wifi display control moves
1528 // to the media router service.
1530 final long token = Binder.clearCallingIdentity();
1532 disconnectWifiDisplayInternal();
1534 Binder.restoreCallingIdentity(token);
1538 @Override // Binder call
1539 public void renameWifiDisplay(String address, String alias) {
1540 if (address == null) {
1541 throw new IllegalArgumentException("address must not be null");
1543 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1544 "Permission required to rename to a wifi display");
1546 final long token = Binder.clearCallingIdentity();
1548 renameWifiDisplayInternal(address, alias);
1550 Binder.restoreCallingIdentity(token);
1554 @Override // Binder call
1555 public void forgetWifiDisplay(String address) {
1556 if (address == null) {
1557 throw new IllegalArgumentException("address must not be null");
1559 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1560 "Permission required to forget to a wifi display");
1562 final long token = Binder.clearCallingIdentity();
1564 forgetWifiDisplayInternal(address);
1566 Binder.restoreCallingIdentity(token);
1570 @Override // Binder call
1571 public void pauseWifiDisplay() {
1572 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1573 "Permission required to pause a wifi display session");
1575 final long token = Binder.clearCallingIdentity();
1577 pauseWifiDisplayInternal();
1579 Binder.restoreCallingIdentity(token);
1583 @Override // Binder call
1584 public void resumeWifiDisplay() {
1585 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1586 "Permission required to resume a wifi display session");
1588 final long token = Binder.clearCallingIdentity();
1590 resumeWifiDisplayInternal();
1592 Binder.restoreCallingIdentity(token);
1596 @Override // Binder call
1597 public WifiDisplayStatus getWifiDisplayStatus() {
1598 // This request does not require special permissions.
1599 // Any app can get information about available wifi displays.
1601 final long token = Binder.clearCallingIdentity();
1603 return getWifiDisplayStatusInternal();
1605 Binder.restoreCallingIdentity(token);
1609 @Override // Binder call
1610 public void requestColorMode(int displayId, int colorMode) {
1611 mContext.enforceCallingOrSelfPermission(
1612 Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
1613 "Permission required to change the display color mode");
1614 final long token = Binder.clearCallingIdentity();
1616 requestColorModeInternal(displayId, colorMode);
1618 Binder.restoreCallingIdentity(token);
1622 @Override // Binder call
1623 public int createVirtualDisplay(IVirtualDisplayCallback callback,
1624 IMediaProjection projection, String packageName, String name,
1625 int width, int height, int densityDpi, Surface surface, int flags,
1627 final int callingUid = Binder.getCallingUid();
1628 if (!validatePackageName(callingUid, packageName)) {
1629 throw new SecurityException("packageName must match the calling uid");
1631 if (callback == null) {
1632 throw new IllegalArgumentException("appToken must not be null");
1634 if (TextUtils.isEmpty(name)) {
1635 throw new IllegalArgumentException("name must be non-null and non-empty");
1637 if (width <= 0 || height <= 0 || densityDpi <= 0) {
1638 throw new IllegalArgumentException("width, height, and densityDpi must be "
1639 + "greater than 0");
1641 if (surface != null && surface.isSingleBuffered()) {
1642 throw new IllegalArgumentException("Surface can't be single-buffered");
1645 if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1646 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1648 // Public displays can't be allowed to show content when locked.
1649 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
1650 throw new IllegalArgumentException(
1651 "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
1654 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1655 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1658 if (projection != null) {
1660 if (!getProjectionService().isValidMediaProjection(projection)) {
1661 throw new SecurityException("Invalid media projection");
1663 flags = projection.applyVirtualDisplayFlags(flags);
1664 } catch (RemoteException e) {
1665 throw new SecurityException("unable to validate media projection or flags");
1669 if (callingUid != Process.SYSTEM_UID &&
1670 (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1671 if (!canProjectVideo(projection)) {
1672 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1673 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1674 + "MediaProjection token in order to create a screen sharing virtual "
1678 if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1679 if (!canProjectSecureVideo(projection)) {
1680 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1681 + "or an appropriate MediaProjection token to create a "
1682 + "secure virtual display.");
1686 final long token = Binder.clearCallingIdentity();
1688 return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
1689 name, width, height, densityDpi, surface, flags, uniqueId);
1691 Binder.restoreCallingIdentity(token);
1695 @Override // Binder call
1696 public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
1697 int width, int height, int densityDpi) {
1698 final long token = Binder.clearCallingIdentity();
1700 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
1702 Binder.restoreCallingIdentity(token);
1706 @Override // Binder call
1707 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
1708 if (surface != null && surface.isSingleBuffered()) {
1709 throw new IllegalArgumentException("Surface can't be single-buffered");
1711 final long token = Binder.clearCallingIdentity();
1713 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
1715 Binder.restoreCallingIdentity(token);
1719 @Override // Binder call
1720 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
1721 final long token = Binder.clearCallingIdentity();
1723 releaseVirtualDisplayInternal(callback.asBinder());
1725 Binder.restoreCallingIdentity(token);
1729 @Override // Binder call
1730 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1731 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1733 final long token = Binder.clearCallingIdentity();
1737 Binder.restoreCallingIdentity(token);
1741 private boolean validatePackageName(int uid, String packageName) {
1742 if (packageName != null) {
1743 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1744 if (packageNames != null) {
1745 for (String n : packageNames) {
1746 if (n.equals(packageName)) {
1755 private boolean canProjectVideo(IMediaProjection projection) {
1756 if (projection != null) {
1758 if (projection.canProjectVideo()) {
1761 } catch (RemoteException e) {
1762 Slog.e(TAG, "Unable to query projection service for permissions", e);
1765 if (mContext.checkCallingPermission(
1766 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1767 == PackageManager.PERMISSION_GRANTED) {
1770 return canProjectSecureVideo(projection);
1773 private boolean canProjectSecureVideo(IMediaProjection projection) {
1774 if (projection != null) {
1776 if (projection.canProjectSecureVideo()){
1779 } catch (RemoteException e) {
1780 Slog.e(TAG, "Unable to query projection service for permissions", e);
1783 return mContext.checkCallingPermission(
1784 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1785 == PackageManager.PERMISSION_GRANTED;
1789 private final class LocalService extends DisplayManagerInternal {
1791 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
1792 SensorManager sensorManager) {
1793 synchronized (mSyncRoot) {
1794 DisplayBlanker blanker = new DisplayBlanker() {
1796 public void requestDisplayState(int state, int brightness) {
1797 // The order of operations is important for legacy reasons.
1798 if (state == Display.STATE_OFF) {
1799 requestGlobalDisplayStateInternal(state, brightness);
1802 callbacks.onDisplayStateChange(state);
1804 if (state != Display.STATE_OFF) {
1805 requestGlobalDisplayStateInternal(state, brightness);
1809 mDisplayPowerController = new DisplayPowerController(
1810 mContext, callbacks, handler, sensorManager, blanker);
1815 public boolean requestPowerState(DisplayPowerRequest request,
1816 boolean waitForNegativeProximity) {
1817 return mDisplayPowerController.requestPowerState(request,
1818 waitForNegativeProximity);
1822 public boolean isProximitySensorAvailable() {
1823 return mDisplayPowerController.isProximitySensorAvailable();
1827 public DisplayInfo getDisplayInfo(int displayId) {
1828 return getDisplayInfoInternal(displayId, Process.myUid());
1832 public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1833 if (listener == null) {
1834 throw new IllegalArgumentException("listener must not be null");
1837 registerDisplayTransactionListenerInternal(listener);
1841 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1842 if (listener == null) {
1843 throw new IllegalArgumentException("listener must not be null");
1846 unregisterDisplayTransactionListenerInternal(listener);
1850 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1851 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1855 public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) {
1856 getNonOverrideDisplayInfoInternal(displayId, outInfo);
1860 public void performTraversalInTransactionFromWindowManager() {
1861 performTraversalInTransactionFromWindowManagerInternal();
1865 public void setDisplayProperties(int displayId, boolean hasContent,
1866 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
1867 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
1868 requestedMode, inTraversal);
1872 public void setDisplayOffsets(int displayId, int x, int y) {
1873 setDisplayOffsetsInternal(displayId, x, y);
1877 public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) {
1878 setDisplayAccessUIDsInternal(newDisplayAccessUIDs);
1882 public boolean isUidPresentOnDisplay(int uid, int displayId) {
1883 return isUidPresentOnDisplayInternal(uid, displayId);