• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.display;
18 
19 import com.android.internal.util.IndentingPrintWriter;
20 
21 import android.Manifest;
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.hardware.SensorManager;
25 import android.hardware.display.DisplayManager;
26 import android.hardware.display.DisplayManagerGlobal;
27 import android.hardware.display.DisplayManagerInternal;
28 import android.hardware.display.DisplayViewport;
29 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
30 import android.hardware.display.IDisplayManager;
31 import android.hardware.display.IDisplayManagerCallback;
32 import android.hardware.display.IVirtualDisplayCallback;
33 import android.hardware.display.WifiDisplayStatus;
34 import android.hardware.input.InputManagerInternal;
35 import android.media.projection.IMediaProjection;
36 import android.media.projection.IMediaProjectionManager;
37 import android.os.Binder;
38 import android.os.Handler;
39 import android.os.IBinder;
40 import android.os.IBinder.DeathRecipient;
41 import android.os.Looper;
42 import android.os.Message;
43 import android.os.PowerManager;
44 import android.os.Process;
45 import android.os.RemoteException;
46 import android.os.ServiceManager;
47 import android.os.SystemClock;
48 import android.os.SystemProperties;
49 import android.os.Trace;
50 import android.text.TextUtils;
51 import android.util.Slog;
52 import android.util.SparseArray;
53 import android.view.Display;
54 import android.view.DisplayInfo;
55 import android.view.Surface;
56 import android.view.WindowManagerInternal;
57 
58 import com.android.server.DisplayThread;
59 import com.android.server.LocalServices;
60 import com.android.server.SystemService;
61 import com.android.server.UiThread;
62 
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.util.ArrayList;
66 import java.util.Arrays;
67 import java.util.List;
68 import java.util.concurrent.CopyOnWriteArrayList;
69 
70 /**
71  * Manages attached displays.
72  * <p>
73  * The {@link DisplayManagerService} manages the global lifecycle of displays,
74  * decides how to configure logical displays based on the physical display devices currently
75  * attached, sends notifications to the system and to applications when the state
76  * changes, and so on.
77  * </p><p>
78  * The display manager service relies on a collection of {@link DisplayAdapter} components,
79  * for discovering and configuring physical display devices attached to the system.
80  * There are separate display adapters for each manner that devices are attached:
81  * one display adapter for built-in local displays, one for simulated non-functional
82  * displays when the system is headless, one for simulated overlay displays used for
83  * development, one for wifi displays, etc.
84  * </p><p>
85  * Display adapters are only weakly coupled to the display manager service.
86  * Display adapters communicate changes in display device state to the display manager
87  * service asynchronously via a {@link DisplayAdapter.Listener} registered
88  * by the display manager service.  This separation of concerns is important for
89  * two main reasons.  First, it neatly encapsulates the responsibilities of these
90  * two classes: display adapters handle individual display devices whereas
91  * the display manager service handles the global state.  Second, it eliminates
92  * the potential for deadlocks resulting from asynchronous display device discovery.
93  * </p>
94  *
95  * <h3>Synchronization</h3>
96  * <p>
97  * Because the display manager may be accessed by multiple threads, the synchronization
98  * story gets a little complicated.  In particular, the window manager may call into
99  * the display manager while holding a surface transaction with the expectation that
100  * it can apply changes immediately.  Unfortunately, that means we can't just do
101  * everything asynchronously (*grump*).
102  * </p><p>
103  * To make this work, all of the objects that belong to the display manager must
104  * use the same lock.  We call this lock the synchronization root and it has a unique
105  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
106  * named with the "Locked" suffix.
107  * </p><p>
108  * Where things get tricky is that the display manager is not allowed to make
109  * any potentially reentrant calls, especially into the window manager.  We generally
110  * avoid this by making all potentially reentrant out-calls asynchronous.
111  * </p>
112  */
113 public final class DisplayManagerService extends SystemService {
114     private static final String TAG = "DisplayManagerService";
115     private static final boolean DEBUG = false;
116 
117     // When this system property is set to 0, WFD is forcibly disabled on boot.
118     // When this system property is set to 1, WFD is forcibly enabled on boot.
119     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
120     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
121 
122     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
123 
124     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
125     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
126     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
127     private static final int MSG_REQUEST_TRAVERSAL = 4;
128     private static final int MSG_UPDATE_VIEWPORT = 5;
129 
130     private final Context mContext;
131     private final DisplayManagerHandler mHandler;
132     private final Handler mUiHandler;
133     private final DisplayAdapterListener mDisplayAdapterListener;
134     private WindowManagerInternal mWindowManagerInternal;
135     private InputManagerInternal mInputManagerInternal;
136     private IMediaProjectionManager mProjectionService;
137 
138     // The synchronization root for the display manager.
139     // This lock guards most of the display manager's state.
140     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
141     // into WindowManagerService methods that require mWindowMap while holding this unless you are
142     // very very sure that no deadlock can occur.
143     private final SyncRoot mSyncRoot = new SyncRoot();
144 
145     // True if in safe mode.
146     // This option may disable certain display adapters.
147     public boolean mSafeMode;
148 
149     // True if we are in a special boot mode where only core applications and
150     // services should be started.  This option may disable certain display adapters.
151     public boolean mOnlyCore;
152 
153     // True if the display manager service should pretend there is only one display
154     // and only tell applications about the existence of the default logical display.
155     // The display manager can still mirror content to secondary displays but applications
156     // cannot present unique content on those displays.
157     // Used for demonstration purposes only.
158     private final boolean mSingleDisplayDemoMode;
159 
160     // All callback records indexed by calling process id.
161     public final SparseArray<CallbackRecord> mCallbacks =
162             new SparseArray<CallbackRecord>();
163 
164     // List of all currently registered display adapters.
165     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
166 
167     // List of all currently connected display devices.
168     private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
169 
170     // List of all logical displays indexed by logical display id.
171     private final SparseArray<LogicalDisplay> mLogicalDisplays =
172             new SparseArray<LogicalDisplay>();
173     private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
174 
175     // List of all display transaction listeners.
176     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
177             new CopyOnWriteArrayList<DisplayTransactionListener>();
178 
179     // Display power controller.
180     private DisplayPowerController mDisplayPowerController;
181 
182     // The overall display state, independent of changes that might influence one
183     // display or another in particular.
184     private int mGlobalDisplayState = Display.STATE_ON;
185 
186     // The overall display brightness.
187     // For now, this only applies to the built-in display but we may split it up eventually.
188     private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
189 
190     // Set to true when there are pending display changes that have yet to be applied
191     // to the surface flinger state.
192     private boolean mPendingTraversal;
193 
194     // The Wifi display adapter, or null if not registered.
195     private WifiDisplayAdapter mWifiDisplayAdapter;
196 
197     // The number of active wifi display scan requests.
198     private int mWifiDisplayScanRequestCount;
199 
200     // The virtual display adapter, or null if not registered.
201     private VirtualDisplayAdapter mVirtualDisplayAdapter;
202 
203     // Viewports of the default display and the display that should receive touch
204     // input from an external source.  Used by the input system.
205     private final DisplayViewport mDefaultViewport = new DisplayViewport();
206     private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
207 
208     // Persistent data store for all internal settings maintained by the display manager service.
209     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
210 
211     // Temporary callback list, used when sending display events to applications.
212     // May be used outside of the lock but only on the handler thread.
213     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
214 
215     // Temporary display info, used for comparing display configurations.
216     private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
217 
218     // Temporary viewports, used when sending new viewport information to the
219     // input system.  May be used outside of the lock but only on the handler thread.
220     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
221     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
222 
223     // Temporary list of deferred work to perform when setting the display state.
224     // Only used by requestDisplayState.  The field is self-synchronized and only
225     // intended for use inside of the requestGlobalDisplayStateInternal function.
226     private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
227 
DisplayManagerService(Context context)228     public DisplayManagerService(Context context) {
229         super(context);
230         mContext = context;
231         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
232         mUiHandler = UiThread.getHandler();
233         mDisplayAdapterListener = new DisplayAdapterListener();
234         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
235 
236         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
237         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
238     }
239 
240     @Override
onStart()241     public void onStart() {
242         // We need to pre-load the persistent data store so it's ready before the default display
243         // adapter is up so that we have it's configuration. We could load it lazily, but since
244         // we're going to have to read it in eventually we may as well do it here rather than after
245         // we've waited for the diplay to register itself with us.
246         mPersistentDataStore.loadIfNeeded();
247         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
248 
249         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
250                 true /*allowIsolated*/);
251         publishLocalService(DisplayManagerInternal.class, new LocalService());
252         publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
253     }
254 
255     @Override
onBootPhase(int phase)256     public void onBootPhase(int phase) {
257         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
258             synchronized (mSyncRoot) {
259                 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
260                 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
261                     long delay = timeout - SystemClock.uptimeMillis();
262                     if (delay <= 0) {
263                         throw new RuntimeException("Timeout waiting for default display "
264                                 + "to be initialized.");
265                     }
266                     if (DEBUG) {
267                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
268                     }
269                     try {
270                         mSyncRoot.wait(delay);
271                     } catch (InterruptedException ex) {
272                     }
273                 }
274             }
275         }
276     }
277 
278     // TODO: Use dependencies or a boot phase
windowManagerAndInputReady()279     public void windowManagerAndInputReady() {
280         synchronized (mSyncRoot) {
281             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
282             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
283             scheduleTraversalLocked(false);
284         }
285     }
286 
287     /**
288      * Called when the system is ready to go.
289      */
systemReady(boolean safeMode, boolean onlyCore)290     public void systemReady(boolean safeMode, boolean onlyCore) {
291         synchronized (mSyncRoot) {
292             mSafeMode = safeMode;
293             mOnlyCore = onlyCore;
294         }
295 
296         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
297     }
298 
registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)299     private void registerDisplayTransactionListenerInternal(
300             DisplayTransactionListener listener) {
301         // List is self-synchronized copy-on-write.
302         mDisplayTransactionListeners.add(listener);
303     }
304 
unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)305     private void unregisterDisplayTransactionListenerInternal(
306             DisplayTransactionListener listener) {
307         // List is self-synchronized copy-on-write.
308         mDisplayTransactionListeners.remove(listener);
309     }
310 
setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info)311     private void setDisplayInfoOverrideFromWindowManagerInternal(
312             int displayId, DisplayInfo info) {
313         synchronized (mSyncRoot) {
314             LogicalDisplay display = mLogicalDisplays.get(displayId);
315             if (display != null) {
316                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
317                     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
318                     scheduleTraversalLocked(false);
319                 }
320             }
321         }
322     }
323 
performTraversalInTransactionFromWindowManagerInternal()324     private void performTraversalInTransactionFromWindowManagerInternal() {
325         synchronized (mSyncRoot) {
326             if (!mPendingTraversal) {
327                 return;
328             }
329             mPendingTraversal = false;
330 
331             performTraversalInTransactionLocked();
332         }
333 
334         // List is self-synchronized copy-on-write.
335         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
336             listener.onDisplayTransaction();
337         }
338     }
339 
requestGlobalDisplayStateInternal(int state, int brightness)340     private void requestGlobalDisplayStateInternal(int state, int brightness) {
341         if (state == Display.STATE_UNKNOWN) {
342             state = Display.STATE_ON;
343         }
344         if (state == Display.STATE_OFF) {
345             brightness = PowerManager.BRIGHTNESS_OFF;
346         } else if (brightness < 0) {
347             brightness = PowerManager.BRIGHTNESS_DEFAULT;
348         } else if (brightness > PowerManager.BRIGHTNESS_ON) {
349             brightness = PowerManager.BRIGHTNESS_ON;
350         }
351 
352         synchronized (mTempDisplayStateWorkQueue) {
353             try {
354                 // Update the display state within the lock.
355                 // Note that we do not need to schedule traversals here although it
356                 // may happen as a side-effect of displays changing state.
357                 synchronized (mSyncRoot) {
358                     if (mGlobalDisplayState == state
359                             && mGlobalDisplayBrightness == brightness) {
360                         return; // no change
361                     }
362 
363                     Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
364                             + Display.stateToString(state)
365                             + ", brightness=" + brightness + ")");
366                     mGlobalDisplayState = state;
367                     mGlobalDisplayBrightness = brightness;
368                     applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
369                 }
370 
371                 // Setting the display power state can take hundreds of milliseconds
372                 // to complete so we defer the most expensive part of the work until
373                 // after we have exited the critical section to avoid blocking other
374                 // threads for a long time.
375                 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
376                     mTempDisplayStateWorkQueue.get(i).run();
377                 }
378                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
379             } finally {
380                 mTempDisplayStateWorkQueue.clear();
381             }
382         }
383     }
384 
getDisplayInfoInternal(int displayId, int callingUid)385     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
386         synchronized (mSyncRoot) {
387             LogicalDisplay display = mLogicalDisplays.get(displayId);
388             if (display != null) {
389                 DisplayInfo info = display.getDisplayInfoLocked();
390                 if (info.hasAccess(callingUid)) {
391                     return info;
392                 }
393             }
394             return null;
395         }
396     }
397 
getDisplayIdsInternal(int callingUid)398     private int[] getDisplayIdsInternal(int callingUid) {
399         synchronized (mSyncRoot) {
400             final int count = mLogicalDisplays.size();
401             int[] displayIds = new int[count];
402             int n = 0;
403             for (int i = 0; i < count; i++) {
404                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
405                 DisplayInfo info = display.getDisplayInfoLocked();
406                 if (info.hasAccess(callingUid)) {
407                     displayIds[n++] = mLogicalDisplays.keyAt(i);
408                 }
409             }
410             if (n != count) {
411                 displayIds = Arrays.copyOfRange(displayIds, 0, n);
412             }
413             return displayIds;
414         }
415     }
416 
registerCallbackInternal(IDisplayManagerCallback callback, int callingPid)417     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
418         synchronized (mSyncRoot) {
419             if (mCallbacks.get(callingPid) != null) {
420                 throw new SecurityException("The calling process has already "
421                         + "registered an IDisplayManagerCallback.");
422             }
423 
424             CallbackRecord record = new CallbackRecord(callingPid, callback);
425             try {
426                 IBinder binder = callback.asBinder();
427                 binder.linkToDeath(record, 0);
428             } catch (RemoteException ex) {
429                 // give up
430                 throw new RuntimeException(ex);
431             }
432 
433             mCallbacks.put(callingPid, record);
434         }
435     }
436 
onCallbackDied(CallbackRecord record)437     private void onCallbackDied(CallbackRecord record) {
438         synchronized (mSyncRoot) {
439             mCallbacks.remove(record.mPid);
440             stopWifiDisplayScanLocked(record);
441         }
442     }
443 
startWifiDisplayScanInternal(int callingPid)444     private void startWifiDisplayScanInternal(int callingPid) {
445         synchronized (mSyncRoot) {
446             CallbackRecord record = mCallbacks.get(callingPid);
447             if (record == null) {
448                 throw new IllegalStateException("The calling process has not "
449                         + "registered an IDisplayManagerCallback.");
450             }
451             startWifiDisplayScanLocked(record);
452         }
453     }
454 
startWifiDisplayScanLocked(CallbackRecord record)455     private void startWifiDisplayScanLocked(CallbackRecord record) {
456         if (!record.mWifiDisplayScanRequested) {
457             record.mWifiDisplayScanRequested = true;
458             if (mWifiDisplayScanRequestCount++ == 0) {
459                 if (mWifiDisplayAdapter != null) {
460                     mWifiDisplayAdapter.requestStartScanLocked();
461                 }
462             }
463         }
464     }
465 
stopWifiDisplayScanInternal(int callingPid)466     private void stopWifiDisplayScanInternal(int callingPid) {
467         synchronized (mSyncRoot) {
468             CallbackRecord record = mCallbacks.get(callingPid);
469             if (record == null) {
470                 throw new IllegalStateException("The calling process has not "
471                         + "registered an IDisplayManagerCallback.");
472             }
473             stopWifiDisplayScanLocked(record);
474         }
475     }
476 
stopWifiDisplayScanLocked(CallbackRecord record)477     private void stopWifiDisplayScanLocked(CallbackRecord record) {
478         if (record.mWifiDisplayScanRequested) {
479             record.mWifiDisplayScanRequested = false;
480             if (--mWifiDisplayScanRequestCount == 0) {
481                 if (mWifiDisplayAdapter != null) {
482                     mWifiDisplayAdapter.requestStopScanLocked();
483                 }
484             } else if (mWifiDisplayScanRequestCount < 0) {
485                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
486                         + mWifiDisplayScanRequestCount);
487                 mWifiDisplayScanRequestCount = 0;
488             }
489         }
490     }
491 
connectWifiDisplayInternal(String address)492     private void connectWifiDisplayInternal(String address) {
493         synchronized (mSyncRoot) {
494             if (mWifiDisplayAdapter != null) {
495                 mWifiDisplayAdapter.requestConnectLocked(address);
496             }
497         }
498     }
499 
pauseWifiDisplayInternal()500     private void pauseWifiDisplayInternal() {
501         synchronized (mSyncRoot) {
502             if (mWifiDisplayAdapter != null) {
503                 mWifiDisplayAdapter.requestPauseLocked();
504             }
505         }
506     }
507 
resumeWifiDisplayInternal()508     private void resumeWifiDisplayInternal() {
509         synchronized (mSyncRoot) {
510             if (mWifiDisplayAdapter != null) {
511                 mWifiDisplayAdapter.requestResumeLocked();
512             }
513         }
514     }
515 
disconnectWifiDisplayInternal()516     private void disconnectWifiDisplayInternal() {
517         synchronized (mSyncRoot) {
518             if (mWifiDisplayAdapter != null) {
519                 mWifiDisplayAdapter.requestDisconnectLocked();
520             }
521         }
522     }
523 
renameWifiDisplayInternal(String address, String alias)524     private void renameWifiDisplayInternal(String address, String alias) {
525         synchronized (mSyncRoot) {
526             if (mWifiDisplayAdapter != null) {
527                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
528             }
529         }
530     }
531 
forgetWifiDisplayInternal(String address)532     private void forgetWifiDisplayInternal(String address) {
533         synchronized (mSyncRoot) {
534             if (mWifiDisplayAdapter != null) {
535                 mWifiDisplayAdapter.requestForgetLocked(address);
536             }
537         }
538     }
539 
getWifiDisplayStatusInternal()540     private WifiDisplayStatus getWifiDisplayStatusInternal() {
541         synchronized (mSyncRoot) {
542             if (mWifiDisplayAdapter != null) {
543                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
544             }
545             return new WifiDisplayStatus();
546         }
547     }
548 
requestColorModeInternal(int displayId, int colorMode)549     private void requestColorModeInternal(int displayId, int colorMode) {
550         synchronized (mSyncRoot) {
551             LogicalDisplay display = mLogicalDisplays.get(displayId);
552             if (display != null &&
553                     display.getRequestedColorModeLocked() != colorMode) {
554                 display.setRequestedColorModeLocked(colorMode);
555                 scheduleTraversalLocked(false);
556             }
557         }
558     }
559 
createVirtualDisplayInternal(IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)560     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
561             IMediaProjection projection, int callingUid, String packageName,
562             String name, int width, int height, int densityDpi, Surface surface, int flags) {
563         synchronized (mSyncRoot) {
564             if (mVirtualDisplayAdapter == null) {
565                 Slog.w(TAG, "Rejecting request to create private virtual display "
566                         + "because the virtual display adapter is not available.");
567                 return -1;
568             }
569 
570             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
571                     callback, projection, callingUid, packageName,
572                     name, width, height, densityDpi, surface, flags);
573             if (device == null) {
574                 return -1;
575             }
576 
577             handleDisplayDeviceAddedLocked(device);
578             LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
579             if (display != null) {
580                 return display.getDisplayIdLocked();
581             }
582 
583             // Something weird happened and the logical display was not created.
584             Slog.w(TAG, "Rejecting request to create virtual display "
585                     + "because the logical display was not created.");
586             mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
587             handleDisplayDeviceRemovedLocked(device);
588         }
589         return -1;
590     }
591 
resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)592     private void resizeVirtualDisplayInternal(IBinder appToken,
593             int width, int height, int densityDpi) {
594         synchronized (mSyncRoot) {
595             if (mVirtualDisplayAdapter == null) {
596                 return;
597             }
598 
599             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
600         }
601     }
602 
setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)603     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
604         synchronized (mSyncRoot) {
605             if (mVirtualDisplayAdapter == null) {
606                 return;
607             }
608 
609             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
610         }
611     }
612 
releaseVirtualDisplayInternal(IBinder appToken)613     private void releaseVirtualDisplayInternal(IBinder appToken) {
614         synchronized (mSyncRoot) {
615             if (mVirtualDisplayAdapter == null) {
616                 return;
617             }
618 
619             DisplayDevice device =
620                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
621             if (device != null) {
622                 handleDisplayDeviceRemovedLocked(device);
623             }
624         }
625     }
626 
registerDefaultDisplayAdapter()627     private void registerDefaultDisplayAdapter() {
628         // Register default display adapter.
629         synchronized (mSyncRoot) {
630             registerDisplayAdapterLocked(new LocalDisplayAdapter(
631                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
632         }
633     }
634 
registerAdditionalDisplayAdapters()635     private void registerAdditionalDisplayAdapters() {
636         synchronized (mSyncRoot) {
637             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
638                 registerOverlayDisplayAdapterLocked();
639                 registerWifiDisplayAdapterLocked();
640                 registerVirtualDisplayAdapterLocked();
641             }
642         }
643     }
644 
registerOverlayDisplayAdapterLocked()645     private void registerOverlayDisplayAdapterLocked() {
646         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
647                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
648     }
649 
registerWifiDisplayAdapterLocked()650     private void registerWifiDisplayAdapterLocked() {
651         if (mContext.getResources().getBoolean(
652                 com.android.internal.R.bool.config_enableWifiDisplay)
653                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
654             mWifiDisplayAdapter = new WifiDisplayAdapter(
655                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
656                     mPersistentDataStore);
657             registerDisplayAdapterLocked(mWifiDisplayAdapter);
658         }
659     }
660 
registerVirtualDisplayAdapterLocked()661     private void registerVirtualDisplayAdapterLocked() {
662         mVirtualDisplayAdapter = new VirtualDisplayAdapter(
663                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
664         registerDisplayAdapterLocked(mVirtualDisplayAdapter);
665     }
666 
shouldRegisterNonEssentialDisplayAdaptersLocked()667     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
668         // In safe mode, we disable non-essential display adapters to give the user
669         // an opportunity to fix broken settings or other problems that might affect
670         // system stability.
671         // In only-core mode, we disable non-essential display adapters to minimize
672         // the number of dependencies that are started while in this mode and to
673         // prevent problems that might occur due to the device being encrypted.
674         return !mSafeMode && !mOnlyCore;
675     }
676 
registerDisplayAdapterLocked(DisplayAdapter adapter)677     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
678         mDisplayAdapters.add(adapter);
679         adapter.registerLocked();
680     }
681 
handleDisplayDeviceAdded(DisplayDevice device)682     private void handleDisplayDeviceAdded(DisplayDevice device) {
683         synchronized (mSyncRoot) {
684             handleDisplayDeviceAddedLocked(device);
685         }
686     }
687 
handleDisplayDeviceAddedLocked(DisplayDevice device)688     private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
689         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
690         if (mDisplayDevices.contains(device)) {
691             Slog.w(TAG, "Attempted to add already added display device: " + info);
692             return;
693         }
694 
695         Slog.i(TAG, "Display device added: " + info);
696         device.mDebugLastLoggedDeviceInfo = info;
697 
698         mDisplayDevices.add(device);
699         LogicalDisplay display = addLogicalDisplayLocked(device);
700         Runnable work = updateDisplayStateLocked(device);
701         if (work != null) {
702             work.run();
703         }
704         if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
705             int colorMode = mPersistentDataStore.getColorMode(device);
706             display.setRequestedColorModeLocked(colorMode);
707         }
708         scheduleTraversalLocked(false);
709     }
710 
handleDisplayDeviceChanged(DisplayDevice device)711     private void handleDisplayDeviceChanged(DisplayDevice device) {
712         synchronized (mSyncRoot) {
713             DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
714             if (!mDisplayDevices.contains(device)) {
715                 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
716                 return;
717             }
718 
719             int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
720             if (diff == DisplayDeviceInfo.DIFF_STATE) {
721                 Slog.i(TAG, "Display device changed state: \"" + info.name
722                         + "\", " + Display.stateToString(info.state));
723             } else if (diff != 0) {
724                 Slog.i(TAG, "Display device changed: " + info);
725             }
726             if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
727                 try {
728                     mPersistentDataStore.setColorMode(device, info.colorMode);
729                 } finally {
730                     mPersistentDataStore.saveIfNeeded();
731                 }
732             }
733             device.mDebugLastLoggedDeviceInfo = info;
734 
735             device.applyPendingDisplayDeviceInfoChangesLocked();
736             if (updateLogicalDisplaysLocked()) {
737                 scheduleTraversalLocked(false);
738             }
739         }
740     }
741 
handleDisplayDeviceRemoved(DisplayDevice device)742     private void handleDisplayDeviceRemoved(DisplayDevice device) {
743         synchronized (mSyncRoot) {
744             handleDisplayDeviceRemovedLocked(device);
745         }
746     }
747 
handleDisplayDeviceRemovedLocked(DisplayDevice device)748     private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
749         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
750         if (!mDisplayDevices.remove(device)) {
751             Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
752             return;
753         }
754 
755         Slog.i(TAG, "Display device removed: " + info);
756         device.mDebugLastLoggedDeviceInfo = info;
757 
758         updateLogicalDisplaysLocked();
759         scheduleTraversalLocked(false);
760     }
761 
applyGlobalDisplayStateLocked(List<Runnable> workQueue)762     private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
763         final int count = mDisplayDevices.size();
764         for (int i = 0; i < count; i++) {
765             DisplayDevice device = mDisplayDevices.get(i);
766             Runnable runnable = updateDisplayStateLocked(device);
767             if (runnable != null) {
768                 workQueue.add(runnable);
769             }
770         }
771     }
772 
updateDisplayStateLocked(DisplayDevice device)773     private Runnable updateDisplayStateLocked(DisplayDevice device) {
774         // Blank or unblank the display immediately to match the state requested
775         // by the display power controller (if known).
776         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
777         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
778             return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
779         }
780         return null;
781     }
782 
783     // Adds a new logical display based on the given display device.
784     // Sends notifications if needed.
addLogicalDisplayLocked(DisplayDevice device)785     private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
786         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
787         boolean isDefault = (deviceInfo.flags
788                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
789         if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
790             Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
791             isDefault = false;
792         }
793 
794         if (!isDefault && mSingleDisplayDemoMode) {
795             Slog.i(TAG, "Not creating a logical display for a secondary display "
796                     + " because single display demo mode is enabled: " + deviceInfo);
797             return null;
798         }
799 
800         final int displayId = assignDisplayIdLocked(isDefault);
801         final int layerStack = assignLayerStackLocked(displayId);
802 
803         LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
804         display.updateLocked(mDisplayDevices);
805         if (!display.isValidLocked()) {
806             // This should never happen currently.
807             Slog.w(TAG, "Ignoring display device because the logical display "
808                     + "created from it was not considered valid: " + deviceInfo);
809             return null;
810         }
811 
812         mLogicalDisplays.put(displayId, display);
813 
814         // Wake up waitForDefaultDisplay.
815         if (isDefault) {
816             mSyncRoot.notifyAll();
817         }
818 
819         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
820         return display;
821     }
822 
assignDisplayIdLocked(boolean isDefault)823     private int assignDisplayIdLocked(boolean isDefault) {
824         return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
825     }
826 
assignLayerStackLocked(int displayId)827     private int assignLayerStackLocked(int displayId) {
828         // Currently layer stacks and display ids are the same.
829         // This need not be the case.
830         return displayId;
831     }
832 
833     // Updates all existing logical displays given the current set of display devices.
834     // Removes invalid logical displays.
835     // Sends notifications if needed.
updateLogicalDisplaysLocked()836     private boolean updateLogicalDisplaysLocked() {
837         boolean changed = false;
838         for (int i = mLogicalDisplays.size(); i-- > 0; ) {
839             final int displayId = mLogicalDisplays.keyAt(i);
840             LogicalDisplay display = mLogicalDisplays.valueAt(i);
841 
842             mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
843             display.updateLocked(mDisplayDevices);
844             if (!display.isValidLocked()) {
845                 mLogicalDisplays.removeAt(i);
846                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
847                 changed = true;
848             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
849                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
850                 changed = true;
851             }
852         }
853         return changed;
854     }
855 
performTraversalInTransactionLocked()856     private void performTraversalInTransactionLocked() {
857         // Clear all viewports before configuring displays so that we can keep
858         // track of which ones we have configured.
859         clearViewportsLocked();
860 
861         // Configure each display device.
862         final int count = mDisplayDevices.size();
863         for (int i = 0; i < count; i++) {
864             DisplayDevice device = mDisplayDevices.get(i);
865             configureDisplayInTransactionLocked(device);
866             device.performTraversalInTransactionLocked();
867         }
868 
869         // Tell the input system about these new viewports.
870         if (mInputManagerInternal != null) {
871             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
872         }
873     }
874 
setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, boolean inTraversal)875     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
876             float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
877         synchronized (mSyncRoot) {
878             LogicalDisplay display = mLogicalDisplays.get(displayId);
879             if (display == null) {
880                 return;
881             }
882             if (display.hasContentLocked() != hasContent) {
883                 if (DEBUG) {
884                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
885                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
886                 }
887 
888                 display.setHasContentLocked(hasContent);
889                 scheduleTraversalLocked(inTraversal);
890             }
891             if (requestedModeId == 0 && requestedRefreshRate != 0) {
892                 // Scan supported modes returned by display.getInfo() to find a mode with the same
893                 // size as the default display mode but with the specified refresh rate instead.
894                 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
895                         requestedRefreshRate);
896             }
897             if (display.getRequestedModeIdLocked() != requestedModeId) {
898                 if (DEBUG) {
899                     Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
900                 }
901                 display.setRequestedModeIdLocked(requestedModeId);
902                 scheduleTraversalLocked(inTraversal);
903             }
904         }
905     }
906 
setDisplayOffsetsInternal(int displayId, int x, int y)907     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
908         synchronized (mSyncRoot) {
909             LogicalDisplay display = mLogicalDisplays.get(displayId);
910             if (display == null) {
911                 return;
912             }
913             if (display.getDisplayOffsetXLocked() != x
914                     || display.getDisplayOffsetYLocked() != y) {
915                 if (DEBUG) {
916                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
917                             + x + ", " + y + ")");
918                 }
919                 display.setDisplayOffsetsLocked(x, y);
920                 scheduleTraversalLocked(false);
921             }
922         }
923     }
924 
clearViewportsLocked()925     private void clearViewportsLocked() {
926         mDefaultViewport.valid = false;
927         mExternalTouchViewport.valid = false;
928     }
929 
configureDisplayInTransactionLocked(DisplayDevice device)930     private void configureDisplayInTransactionLocked(DisplayDevice device) {
931         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
932         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
933 
934         // Find the logical display that the display device is showing.
935         // Certain displays only ever show their own content.
936         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
937         if (!ownContent) {
938             if (display != null && !display.hasContentLocked()) {
939                 // If the display does not have any content of its own, then
940                 // automatically mirror the default logical display contents.
941                 display = null;
942             }
943             if (display == null) {
944                 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
945             }
946         }
947 
948         // Apply the logical display configuration to the display device.
949         if (display == null) {
950             // TODO: no logical display for the device, blank it
951             Slog.w(TAG, "Missing logical display to use for physical display device: "
952                     + device.getDisplayDeviceInfoLocked());
953             return;
954         }
955         display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
956 
957         // Update the viewports if needed.
958         if (!mDefaultViewport.valid
959                 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
960             setViewportLocked(mDefaultViewport, display, device);
961         }
962         if (!mExternalTouchViewport.valid
963                 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
964             setViewportLocked(mExternalTouchViewport, display, device);
965         }
966     }
967 
setViewportLocked(DisplayViewport viewport, LogicalDisplay display, DisplayDevice device)968     private static void setViewportLocked(DisplayViewport viewport,
969             LogicalDisplay display, DisplayDevice device) {
970         viewport.valid = true;
971         viewport.displayId = display.getDisplayIdLocked();
972         device.populateViewportLocked(viewport);
973     }
974 
findLogicalDisplayForDeviceLocked(DisplayDevice device)975     private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
976         final int count = mLogicalDisplays.size();
977         for (int i = 0; i < count; i++) {
978             LogicalDisplay display = mLogicalDisplays.valueAt(i);
979             if (display.getPrimaryDisplayDeviceLocked() == device) {
980                 return display;
981             }
982         }
983         return null;
984     }
985 
sendDisplayEventLocked(int displayId, int event)986     private void sendDisplayEventLocked(int displayId, int event) {
987         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
988         mHandler.sendMessage(msg);
989     }
990 
991     // Requests that performTraversalsInTransactionFromWindowManager be called at a
992     // later time to apply changes to surfaces and displays.
scheduleTraversalLocked(boolean inTraversal)993     private void scheduleTraversalLocked(boolean inTraversal) {
994         if (!mPendingTraversal && mWindowManagerInternal != null) {
995             mPendingTraversal = true;
996             if (!inTraversal) {
997                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
998             }
999         }
1000     }
1001 
1002     // Runs on Handler thread.
1003     // Delivers display event notifications to callbacks.
deliverDisplayEvent(int displayId, int event)1004     private void deliverDisplayEvent(int displayId, int event) {
1005         if (DEBUG) {
1006             Slog.d(TAG, "Delivering display event: displayId="
1007                     + displayId + ", event=" + event);
1008         }
1009 
1010         // Grab the lock and copy the callbacks.
1011         final int count;
1012         synchronized (mSyncRoot) {
1013             count = mCallbacks.size();
1014             mTempCallbacks.clear();
1015             for (int i = 0; i < count; i++) {
1016                 mTempCallbacks.add(mCallbacks.valueAt(i));
1017             }
1018         }
1019 
1020         // After releasing the lock, send the notifications out.
1021         for (int i = 0; i < count; i++) {
1022             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1023         }
1024         mTempCallbacks.clear();
1025     }
1026 
getProjectionService()1027     private IMediaProjectionManager getProjectionService() {
1028         if (mProjectionService == null) {
1029             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1030             mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1031         }
1032         return mProjectionService;
1033     }
1034 
dumpInternal(PrintWriter pw)1035     private void dumpInternal(PrintWriter pw) {
1036         pw.println("DISPLAY MANAGER (dumpsys display)");
1037 
1038         synchronized (mSyncRoot) {
1039             pw.println("  mOnlyCode=" + mOnlyCore);
1040             pw.println("  mSafeMode=" + mSafeMode);
1041             pw.println("  mPendingTraversal=" + mPendingTraversal);
1042             pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
1043             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1044             pw.println("  mDefaultViewport=" + mDefaultViewport);
1045             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
1046             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
1047             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
1048 
1049             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
1050             ipw.increaseIndent();
1051 
1052             pw.println();
1053             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
1054             for (DisplayAdapter adapter : mDisplayAdapters) {
1055                 pw.println("  " + adapter.getName());
1056                 adapter.dumpLocked(ipw);
1057             }
1058 
1059             pw.println();
1060             pw.println("Display Devices: size=" + mDisplayDevices.size());
1061             for (DisplayDevice device : mDisplayDevices) {
1062                 pw.println("  " + device.getDisplayDeviceInfoLocked());
1063                 device.dumpLocked(ipw);
1064             }
1065 
1066             final int logicalDisplayCount = mLogicalDisplays.size();
1067             pw.println();
1068             pw.println("Logical Displays: size=" + logicalDisplayCount);
1069             for (int i = 0; i < logicalDisplayCount; i++) {
1070                 int displayId = mLogicalDisplays.keyAt(i);
1071                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1072                 pw.println("  Display " + displayId + ":");
1073                 display.dumpLocked(ipw);
1074             }
1075 
1076             final int callbackCount = mCallbacks.size();
1077             pw.println();
1078             pw.println("Callbacks: size=" + callbackCount);
1079             for (int i = 0; i < callbackCount; i++) {
1080                 CallbackRecord callback = mCallbacks.valueAt(i);
1081                 pw.println("  " + i + ": mPid=" + callback.mPid
1082                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
1083             }
1084 
1085             if (mDisplayPowerController != null) {
1086                 mDisplayPowerController.dump(pw);
1087             }
1088 
1089             pw.println();
1090             mPersistentDataStore.dump(pw);
1091         }
1092     }
1093 
1094     /**
1095      * This is the object that everything in the display manager locks on.
1096      * We make it an inner class within the {@link DisplayManagerService} to so that it is
1097      * clear that the object belongs to the display manager service and that it is
1098      * a unique object with a special purpose.
1099      */
1100     public static final class SyncRoot {
1101     }
1102 
1103     private final class DisplayManagerHandler extends Handler {
DisplayManagerHandler(Looper looper)1104         public DisplayManagerHandler(Looper looper) {
1105             super(looper, null, true /*async*/);
1106         }
1107 
1108         @Override
handleMessage(Message msg)1109         public void handleMessage(Message msg) {
1110             switch (msg.what) {
1111                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
1112                     registerDefaultDisplayAdapter();
1113                     break;
1114 
1115                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1116                     registerAdditionalDisplayAdapters();
1117                     break;
1118 
1119                 case MSG_DELIVER_DISPLAY_EVENT:
1120                     deliverDisplayEvent(msg.arg1, msg.arg2);
1121                     break;
1122 
1123                 case MSG_REQUEST_TRAVERSAL:
1124                     mWindowManagerInternal.requestTraversalFromDisplayManager();
1125                     break;
1126 
1127                 case MSG_UPDATE_VIEWPORT: {
1128                     synchronized (mSyncRoot) {
1129                         mTempDefaultViewport.copyFrom(mDefaultViewport);
1130                         mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1131                     }
1132                     mInputManagerInternal.setDisplayViewports(
1133                             mTempDefaultViewport, mTempExternalTouchViewport);
1134                     break;
1135                 }
1136             }
1137         }
1138     }
1139 
1140     private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1141         @Override
onDisplayDeviceEvent(DisplayDevice device, int event)1142         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1143             switch (event) {
1144                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1145                     handleDisplayDeviceAdded(device);
1146                     break;
1147 
1148                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1149                     handleDisplayDeviceChanged(device);
1150                     break;
1151 
1152                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1153                     handleDisplayDeviceRemoved(device);
1154                     break;
1155             }
1156         }
1157 
1158         @Override
onTraversalRequested()1159         public void onTraversalRequested() {
1160             synchronized (mSyncRoot) {
1161                 scheduleTraversalLocked(false);
1162             }
1163         }
1164     }
1165 
1166     private final class CallbackRecord implements DeathRecipient {
1167         public final int mPid;
1168         private final IDisplayManagerCallback mCallback;
1169 
1170         public boolean mWifiDisplayScanRequested;
1171 
CallbackRecord(int pid, IDisplayManagerCallback callback)1172         public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1173             mPid = pid;
1174             mCallback = callback;
1175         }
1176 
1177         @Override
binderDied()1178         public void binderDied() {
1179             if (DEBUG) {
1180                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1181             }
1182             onCallbackDied(this);
1183         }
1184 
notifyDisplayEventAsync(int displayId, int event)1185         public void notifyDisplayEventAsync(int displayId, int event) {
1186             try {
1187                 mCallback.onDisplayEvent(displayId, event);
1188             } catch (RemoteException ex) {
1189                 Slog.w(TAG, "Failed to notify process "
1190                         + mPid + " that displays changed, assuming it died.", ex);
1191                 binderDied();
1192             }
1193         }
1194     }
1195 
1196     private final class BinderService extends IDisplayManager.Stub {
1197         /**
1198          * Returns information about the specified logical display.
1199          *
1200          * @param displayId The logical display id.
1201          * @return The logical display info, or null if the display does not exist.  The
1202          * returned object must be treated as immutable.
1203          */
1204         @Override // Binder call
getDisplayInfo(int displayId)1205         public DisplayInfo getDisplayInfo(int displayId) {
1206             final int callingUid = Binder.getCallingUid();
1207             final long token = Binder.clearCallingIdentity();
1208             try {
1209                 return getDisplayInfoInternal(displayId, callingUid);
1210             } finally {
1211                 Binder.restoreCallingIdentity(token);
1212             }
1213         }
1214 
1215         /**
1216          * Returns the list of all display ids.
1217          */
1218         @Override // Binder call
getDisplayIds()1219         public int[] getDisplayIds() {
1220             final int callingUid = Binder.getCallingUid();
1221             final long token = Binder.clearCallingIdentity();
1222             try {
1223                 return getDisplayIdsInternal(callingUid);
1224             } finally {
1225                 Binder.restoreCallingIdentity(token);
1226             }
1227         }
1228 
1229         @Override // Binder call
registerCallback(IDisplayManagerCallback callback)1230         public void registerCallback(IDisplayManagerCallback callback) {
1231             if (callback == null) {
1232                 throw new IllegalArgumentException("listener must not be null");
1233             }
1234 
1235             final int callingPid = Binder.getCallingPid();
1236             final long token = Binder.clearCallingIdentity();
1237             try {
1238                 registerCallbackInternal(callback, callingPid);
1239             } finally {
1240                 Binder.restoreCallingIdentity(token);
1241             }
1242         }
1243 
1244         @Override // Binder call
startWifiDisplayScan()1245         public void startWifiDisplayScan() {
1246             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1247                     "Permission required to start wifi display scans");
1248 
1249             final int callingPid = Binder.getCallingPid();
1250             final long token = Binder.clearCallingIdentity();
1251             try {
1252                 startWifiDisplayScanInternal(callingPid);
1253             } finally {
1254                 Binder.restoreCallingIdentity(token);
1255             }
1256         }
1257 
1258         @Override // Binder call
stopWifiDisplayScan()1259         public void stopWifiDisplayScan() {
1260             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1261                     "Permission required to stop wifi display scans");
1262 
1263             final int callingPid = Binder.getCallingPid();
1264             final long token = Binder.clearCallingIdentity();
1265             try {
1266                 stopWifiDisplayScanInternal(callingPid);
1267             } finally {
1268                 Binder.restoreCallingIdentity(token);
1269             }
1270         }
1271 
1272         @Override // Binder call
connectWifiDisplay(String address)1273         public void connectWifiDisplay(String address) {
1274             if (address == null) {
1275                 throw new IllegalArgumentException("address must not be null");
1276             }
1277             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1278                     "Permission required to connect to a wifi display");
1279 
1280             final long token = Binder.clearCallingIdentity();
1281             try {
1282                 connectWifiDisplayInternal(address);
1283             } finally {
1284                 Binder.restoreCallingIdentity(token);
1285             }
1286         }
1287 
1288         @Override // Binder call
disconnectWifiDisplay()1289         public void disconnectWifiDisplay() {
1290             // This request does not require special permissions.
1291             // Any app can request disconnection from the currently active wifi display.
1292             // This exception should no longer be needed once wifi display control moves
1293             // to the media router service.
1294 
1295             final long token = Binder.clearCallingIdentity();
1296             try {
1297                 disconnectWifiDisplayInternal();
1298             } finally {
1299                 Binder.restoreCallingIdentity(token);
1300             }
1301         }
1302 
1303         @Override // Binder call
renameWifiDisplay(String address, String alias)1304         public void renameWifiDisplay(String address, String alias) {
1305             if (address == null) {
1306                 throw new IllegalArgumentException("address must not be null");
1307             }
1308             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1309                     "Permission required to rename to a wifi display");
1310 
1311             final long token = Binder.clearCallingIdentity();
1312             try {
1313                 renameWifiDisplayInternal(address, alias);
1314             } finally {
1315                 Binder.restoreCallingIdentity(token);
1316             }
1317         }
1318 
1319         @Override // Binder call
forgetWifiDisplay(String address)1320         public void forgetWifiDisplay(String address) {
1321             if (address == null) {
1322                 throw new IllegalArgumentException("address must not be null");
1323             }
1324             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1325                     "Permission required to forget to a wifi display");
1326 
1327             final long token = Binder.clearCallingIdentity();
1328             try {
1329                 forgetWifiDisplayInternal(address);
1330             } finally {
1331                 Binder.restoreCallingIdentity(token);
1332             }
1333         }
1334 
1335         @Override // Binder call
pauseWifiDisplay()1336         public void pauseWifiDisplay() {
1337             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1338                     "Permission required to pause a wifi display session");
1339 
1340             final long token = Binder.clearCallingIdentity();
1341             try {
1342                 pauseWifiDisplayInternal();
1343             } finally {
1344                 Binder.restoreCallingIdentity(token);
1345             }
1346         }
1347 
1348         @Override // Binder call
resumeWifiDisplay()1349         public void resumeWifiDisplay() {
1350             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1351                     "Permission required to resume a wifi display session");
1352 
1353             final long token = Binder.clearCallingIdentity();
1354             try {
1355                 resumeWifiDisplayInternal();
1356             } finally {
1357                 Binder.restoreCallingIdentity(token);
1358             }
1359         }
1360 
1361         @Override // Binder call
getWifiDisplayStatus()1362         public WifiDisplayStatus getWifiDisplayStatus() {
1363             // This request does not require special permissions.
1364             // Any app can get information about available wifi displays.
1365 
1366             final long token = Binder.clearCallingIdentity();
1367             try {
1368                 return getWifiDisplayStatusInternal();
1369             } finally {
1370                 Binder.restoreCallingIdentity(token);
1371             }
1372         }
1373 
1374         @Override // Binder call
requestColorMode(int displayId, int colorMode)1375         public void requestColorMode(int displayId, int colorMode) {
1376             mContext.enforceCallingOrSelfPermission(
1377                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
1378                     "Permission required to change the display color mode");
1379             final long token = Binder.clearCallingIdentity();
1380             try {
1381                 requestColorModeInternal(displayId, colorMode);
1382             } finally {
1383                 Binder.restoreCallingIdentity(token);
1384             }
1385         }
1386 
1387         @Override // Binder call
createVirtualDisplay(IVirtualDisplayCallback callback, IMediaProjection projection, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)1388         public int createVirtualDisplay(IVirtualDisplayCallback callback,
1389                 IMediaProjection projection, String packageName, String name,
1390                 int width, int height, int densityDpi, Surface surface, int flags) {
1391             final int callingUid = Binder.getCallingUid();
1392             if (!validatePackageName(callingUid, packageName)) {
1393                 throw new SecurityException("packageName must match the calling uid");
1394             }
1395             if (callback == null) {
1396                 throw new IllegalArgumentException("appToken must not be null");
1397             }
1398             if (TextUtils.isEmpty(name)) {
1399                 throw new IllegalArgumentException("name must be non-null and non-empty");
1400             }
1401             if (width <= 0 || height <= 0 || densityDpi <= 0) {
1402                 throw new IllegalArgumentException("width, height, and densityDpi must be "
1403                         + "greater than 0");
1404             }
1405 
1406             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1407                 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1408             }
1409             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1410                 flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1411             }
1412 
1413             if (projection != null) {
1414                 try {
1415                     if (!getProjectionService().isValidMediaProjection(projection)) {
1416                         throw new SecurityException("Invalid media projection");
1417                     }
1418                     flags = projection.applyVirtualDisplayFlags(flags);
1419                 } catch (RemoteException e) {
1420                     throw new SecurityException("unable to validate media projection or flags");
1421                 }
1422             }
1423 
1424             if (callingUid != Process.SYSTEM_UID &&
1425                     (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1426                 if (!canProjectVideo(projection)) {
1427                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1428                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1429                             + "MediaProjection token in order to create a screen sharing virtual "
1430                             + "display.");
1431                 }
1432             }
1433             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1434                 if (!canProjectSecureVideo(projection)) {
1435                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1436                             + "or an appropriate MediaProjection token to create a "
1437                             + "secure virtual display.");
1438                 }
1439             }
1440 
1441             final long token = Binder.clearCallingIdentity();
1442             try {
1443                 return createVirtualDisplayInternal(callback, projection, callingUid,
1444                         packageName, name, width, height, densityDpi, surface, flags);
1445             } finally {
1446                 Binder.restoreCallingIdentity(token);
1447             }
1448         }
1449 
1450         @Override // Binder call
resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)1451         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
1452                 int width, int height, int densityDpi) {
1453             final long token = Binder.clearCallingIdentity();
1454             try {
1455                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
1456             } finally {
1457                 Binder.restoreCallingIdentity(token);
1458             }
1459         }
1460 
1461         @Override // Binder call
setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)1462         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
1463             final long token = Binder.clearCallingIdentity();
1464             try {
1465                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
1466             } finally {
1467                 Binder.restoreCallingIdentity(token);
1468             }
1469         }
1470 
1471         @Override // Binder call
releaseVirtualDisplay(IVirtualDisplayCallback callback)1472         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
1473             final long token = Binder.clearCallingIdentity();
1474             try {
1475                 releaseVirtualDisplayInternal(callback.asBinder());
1476             } finally {
1477                 Binder.restoreCallingIdentity(token);
1478             }
1479         }
1480 
1481         @Override // Binder call
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1482         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1483             if (mContext == null
1484                     || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1485                             != PackageManager.PERMISSION_GRANTED) {
1486                 pw.println("Permission Denial: can't dump DisplayManager from from pid="
1487                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1488                 return;
1489             }
1490 
1491             final long token = Binder.clearCallingIdentity();
1492             try {
1493                 dumpInternal(pw);
1494             } finally {
1495                 Binder.restoreCallingIdentity(token);
1496             }
1497         }
1498 
validatePackageName(int uid, String packageName)1499         private boolean validatePackageName(int uid, String packageName) {
1500             if (packageName != null) {
1501                 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1502                 if (packageNames != null) {
1503                     for (String n : packageNames) {
1504                         if (n.equals(packageName)) {
1505                             return true;
1506                         }
1507                     }
1508                 }
1509             }
1510             return false;
1511         }
1512 
canProjectVideo(IMediaProjection projection)1513         private boolean canProjectVideo(IMediaProjection projection) {
1514             if (projection != null) {
1515                 try {
1516                     if (projection.canProjectVideo()) {
1517                         return true;
1518                     }
1519                 } catch (RemoteException e) {
1520                     Slog.e(TAG, "Unable to query projection service for permissions", e);
1521                 }
1522             }
1523             if (mContext.checkCallingPermission(
1524                     android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1525                     == PackageManager.PERMISSION_GRANTED) {
1526                 return true;
1527             }
1528             return canProjectSecureVideo(projection);
1529         }
1530 
canProjectSecureVideo(IMediaProjection projection)1531         private boolean canProjectSecureVideo(IMediaProjection projection) {
1532             if (projection != null) {
1533                 try {
1534                     if (projection.canProjectSecureVideo()){
1535                         return true;
1536                     }
1537                 } catch (RemoteException e) {
1538                     Slog.e(TAG, "Unable to query projection service for permissions", e);
1539                 }
1540             }
1541             return mContext.checkCallingPermission(
1542                     android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1543                     == PackageManager.PERMISSION_GRANTED;
1544         }
1545     }
1546 
1547     private final class LocalService extends DisplayManagerInternal {
1548         @Override
initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)1549         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
1550                 SensorManager sensorManager) {
1551             synchronized (mSyncRoot) {
1552                 DisplayBlanker blanker = new DisplayBlanker() {
1553                     @Override
1554                     public void requestDisplayState(int state, int brightness) {
1555                         // The order of operations is important for legacy reasons.
1556                         if (state == Display.STATE_OFF) {
1557                             requestGlobalDisplayStateInternal(state, brightness);
1558                         }
1559 
1560                         callbacks.onDisplayStateChange(state);
1561 
1562                         if (state != Display.STATE_OFF) {
1563                             requestGlobalDisplayStateInternal(state, brightness);
1564                         }
1565                     }
1566                 };
1567                 mDisplayPowerController = new DisplayPowerController(
1568                         mContext, callbacks, handler, sensorManager, blanker);
1569             }
1570         }
1571 
1572         @Override
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)1573         public boolean requestPowerState(DisplayPowerRequest request,
1574                 boolean waitForNegativeProximity) {
1575             return mDisplayPowerController.requestPowerState(request,
1576                     waitForNegativeProximity);
1577         }
1578 
1579         @Override
isProximitySensorAvailable()1580         public boolean isProximitySensorAvailable() {
1581             return mDisplayPowerController.isProximitySensorAvailable();
1582         }
1583 
1584         @Override
getDisplayInfo(int displayId)1585         public DisplayInfo getDisplayInfo(int displayId) {
1586             return getDisplayInfoInternal(displayId, Process.myUid());
1587         }
1588 
1589         @Override
registerDisplayTransactionListener(DisplayTransactionListener listener)1590         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1591             if (listener == null) {
1592                 throw new IllegalArgumentException("listener must not be null");
1593             }
1594 
1595             registerDisplayTransactionListenerInternal(listener);
1596         }
1597 
1598         @Override
unregisterDisplayTransactionListener(DisplayTransactionListener listener)1599         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1600             if (listener == null) {
1601                 throw new IllegalArgumentException("listener must not be null");
1602             }
1603 
1604             unregisterDisplayTransactionListenerInternal(listener);
1605         }
1606 
1607         @Override
setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)1608         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1609             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1610         }
1611 
1612         @Override
performTraversalInTransactionFromWindowManager()1613         public void performTraversalInTransactionFromWindowManager() {
1614             performTraversalInTransactionFromWindowManagerInternal();
1615         }
1616 
1617         @Override
setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, boolean inTraversal)1618         public void setDisplayProperties(int displayId, boolean hasContent,
1619                 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
1620             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
1621                     requestedMode, inTraversal);
1622         }
1623 
1624         @Override
setDisplayOffsets(int displayId, int x, int y)1625         public void setDisplayOffsets(int displayId, int x, int y) {
1626             setDisplayOffsetsInternal(displayId, x, y);
1627         }
1628     }
1629 }
1630