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         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
243 
244         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
245                 true /*allowIsolated*/);
246         publishLocalService(DisplayManagerInternal.class, new LocalService());
247     }
248 
249     @Override
onBootPhase(int phase)250     public void onBootPhase(int phase) {
251         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
252             synchronized (mSyncRoot) {
253                 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
254                 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
255                     long delay = timeout - SystemClock.uptimeMillis();
256                     if (delay <= 0) {
257                         throw new RuntimeException("Timeout waiting for default display "
258                                 + "to be initialized.");
259                     }
260                     if (DEBUG) {
261                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
262                     }
263                     try {
264                         mSyncRoot.wait(delay);
265                     } catch (InterruptedException ex) {
266                     }
267                 }
268             }
269         }
270     }
271 
272     // TODO: Use dependencies or a boot phase
windowManagerAndInputReady()273     public void windowManagerAndInputReady() {
274         synchronized (mSyncRoot) {
275             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
276             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
277             scheduleTraversalLocked(false);
278         }
279     }
280 
281     /**
282      * Called when the system is ready to go.
283      */
systemReady(boolean safeMode, boolean onlyCore)284     public void systemReady(boolean safeMode, boolean onlyCore) {
285         synchronized (mSyncRoot) {
286             mSafeMode = safeMode;
287             mOnlyCore = onlyCore;
288         }
289 
290         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
291     }
292 
registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)293     private void registerDisplayTransactionListenerInternal(
294             DisplayTransactionListener listener) {
295         // List is self-synchronized copy-on-write.
296         mDisplayTransactionListeners.add(listener);
297     }
298 
unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)299     private void unregisterDisplayTransactionListenerInternal(
300             DisplayTransactionListener listener) {
301         // List is self-synchronized copy-on-write.
302         mDisplayTransactionListeners.remove(listener);
303     }
304 
setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info)305     private void setDisplayInfoOverrideFromWindowManagerInternal(
306             int displayId, DisplayInfo info) {
307         synchronized (mSyncRoot) {
308             LogicalDisplay display = mLogicalDisplays.get(displayId);
309             if (display != null) {
310                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
311                     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
312                     scheduleTraversalLocked(false);
313                 }
314             }
315         }
316     }
317 
performTraversalInTransactionFromWindowManagerInternal()318     private void performTraversalInTransactionFromWindowManagerInternal() {
319         synchronized (mSyncRoot) {
320             if (!mPendingTraversal) {
321                 return;
322             }
323             mPendingTraversal = false;
324 
325             performTraversalInTransactionLocked();
326         }
327 
328         // List is self-synchronized copy-on-write.
329         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
330             listener.onDisplayTransaction();
331         }
332     }
333 
requestGlobalDisplayStateInternal(int state, int brightness)334     private void requestGlobalDisplayStateInternal(int state, int brightness) {
335         if (state == Display.STATE_UNKNOWN) {
336             state = Display.STATE_ON;
337         }
338         if (state == Display.STATE_OFF) {
339             brightness = PowerManager.BRIGHTNESS_OFF;
340         } else if (brightness < 0) {
341             brightness = PowerManager.BRIGHTNESS_DEFAULT;
342         } else if (brightness > PowerManager.BRIGHTNESS_ON) {
343             brightness = PowerManager.BRIGHTNESS_ON;
344         }
345 
346         synchronized (mTempDisplayStateWorkQueue) {
347             try {
348                 // Update the display state within the lock.
349                 // Note that we do not need to schedule traversals here although it
350                 // may happen as a side-effect of displays changing state.
351                 synchronized (mSyncRoot) {
352                     if (mGlobalDisplayState == state
353                             && mGlobalDisplayBrightness == brightness) {
354                         return; // no change
355                     }
356 
357                     Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
358                             + Display.stateToString(state)
359                             + ", brightness=" + brightness + ")");
360                     mGlobalDisplayState = state;
361                     mGlobalDisplayBrightness = brightness;
362                     applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
363                 }
364 
365                 // Setting the display power state can take hundreds of milliseconds
366                 // to complete so we defer the most expensive part of the work until
367                 // after we have exited the critical section to avoid blocking other
368                 // threads for a long time.
369                 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
370                     mTempDisplayStateWorkQueue.get(i).run();
371                 }
372                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
373             } finally {
374                 mTempDisplayStateWorkQueue.clear();
375             }
376         }
377     }
378 
getDisplayInfoInternal(int displayId, int callingUid)379     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
380         synchronized (mSyncRoot) {
381             LogicalDisplay display = mLogicalDisplays.get(displayId);
382             if (display != null) {
383                 DisplayInfo info = display.getDisplayInfoLocked();
384                 if (info.hasAccess(callingUid)) {
385                     return info;
386                 }
387             }
388             return null;
389         }
390     }
391 
getDisplayIdsInternal(int callingUid)392     private int[] getDisplayIdsInternal(int callingUid) {
393         synchronized (mSyncRoot) {
394             final int count = mLogicalDisplays.size();
395             int[] displayIds = new int[count];
396             int n = 0;
397             for (int i = 0; i < count; i++) {
398                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
399                 DisplayInfo info = display.getDisplayInfoLocked();
400                 if (info.hasAccess(callingUid)) {
401                     displayIds[n++] = mLogicalDisplays.keyAt(i);
402                 }
403             }
404             if (n != count) {
405                 displayIds = Arrays.copyOfRange(displayIds, 0, n);
406             }
407             return displayIds;
408         }
409     }
410 
registerCallbackInternal(IDisplayManagerCallback callback, int callingPid)411     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
412         synchronized (mSyncRoot) {
413             if (mCallbacks.get(callingPid) != null) {
414                 throw new SecurityException("The calling process has already "
415                         + "registered an IDisplayManagerCallback.");
416             }
417 
418             CallbackRecord record = new CallbackRecord(callingPid, callback);
419             try {
420                 IBinder binder = callback.asBinder();
421                 binder.linkToDeath(record, 0);
422             } catch (RemoteException ex) {
423                 // give up
424                 throw new RuntimeException(ex);
425             }
426 
427             mCallbacks.put(callingPid, record);
428         }
429     }
430 
onCallbackDied(CallbackRecord record)431     private void onCallbackDied(CallbackRecord record) {
432         synchronized (mSyncRoot) {
433             mCallbacks.remove(record.mPid);
434             stopWifiDisplayScanLocked(record);
435         }
436     }
437 
startWifiDisplayScanInternal(int callingPid)438     private void startWifiDisplayScanInternal(int callingPid) {
439         synchronized (mSyncRoot) {
440             CallbackRecord record = mCallbacks.get(callingPid);
441             if (record == null) {
442                 throw new IllegalStateException("The calling process has not "
443                         + "registered an IDisplayManagerCallback.");
444             }
445             startWifiDisplayScanLocked(record);
446         }
447     }
448 
startWifiDisplayScanLocked(CallbackRecord record)449     private void startWifiDisplayScanLocked(CallbackRecord record) {
450         if (!record.mWifiDisplayScanRequested) {
451             record.mWifiDisplayScanRequested = true;
452             if (mWifiDisplayScanRequestCount++ == 0) {
453                 if (mWifiDisplayAdapter != null) {
454                     mWifiDisplayAdapter.requestStartScanLocked();
455                 }
456             }
457         }
458     }
459 
stopWifiDisplayScanInternal(int callingPid)460     private void stopWifiDisplayScanInternal(int callingPid) {
461         synchronized (mSyncRoot) {
462             CallbackRecord record = mCallbacks.get(callingPid);
463             if (record == null) {
464                 throw new IllegalStateException("The calling process has not "
465                         + "registered an IDisplayManagerCallback.");
466             }
467             stopWifiDisplayScanLocked(record);
468         }
469     }
470 
stopWifiDisplayScanLocked(CallbackRecord record)471     private void stopWifiDisplayScanLocked(CallbackRecord record) {
472         if (record.mWifiDisplayScanRequested) {
473             record.mWifiDisplayScanRequested = false;
474             if (--mWifiDisplayScanRequestCount == 0) {
475                 if (mWifiDisplayAdapter != null) {
476                     mWifiDisplayAdapter.requestStopScanLocked();
477                 }
478             } else if (mWifiDisplayScanRequestCount < 0) {
479                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
480                         + mWifiDisplayScanRequestCount);
481                 mWifiDisplayScanRequestCount = 0;
482             }
483         }
484     }
485 
connectWifiDisplayInternal(String address)486     private void connectWifiDisplayInternal(String address) {
487         synchronized (mSyncRoot) {
488             if (mWifiDisplayAdapter != null) {
489                 mWifiDisplayAdapter.requestConnectLocked(address);
490             }
491         }
492     }
493 
pauseWifiDisplayInternal()494     private void pauseWifiDisplayInternal() {
495         synchronized (mSyncRoot) {
496             if (mWifiDisplayAdapter != null) {
497                 mWifiDisplayAdapter.requestPauseLocked();
498             }
499         }
500     }
501 
resumeWifiDisplayInternal()502     private void resumeWifiDisplayInternal() {
503         synchronized (mSyncRoot) {
504             if (mWifiDisplayAdapter != null) {
505                 mWifiDisplayAdapter.requestResumeLocked();
506             }
507         }
508     }
509 
disconnectWifiDisplayInternal()510     private void disconnectWifiDisplayInternal() {
511         synchronized (mSyncRoot) {
512             if (mWifiDisplayAdapter != null) {
513                 mWifiDisplayAdapter.requestDisconnectLocked();
514             }
515         }
516     }
517 
renameWifiDisplayInternal(String address, String alias)518     private void renameWifiDisplayInternal(String address, String alias) {
519         synchronized (mSyncRoot) {
520             if (mWifiDisplayAdapter != null) {
521                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
522             }
523         }
524     }
525 
forgetWifiDisplayInternal(String address)526     private void forgetWifiDisplayInternal(String address) {
527         synchronized (mSyncRoot) {
528             if (mWifiDisplayAdapter != null) {
529                 mWifiDisplayAdapter.requestForgetLocked(address);
530             }
531         }
532     }
533 
getWifiDisplayStatusInternal()534     private WifiDisplayStatus getWifiDisplayStatusInternal() {
535         synchronized (mSyncRoot) {
536             if (mWifiDisplayAdapter != null) {
537                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
538             }
539             return new WifiDisplayStatus();
540         }
541     }
542 
requestColorTransformInternal(int displayId, int colorTransformId)543     private void requestColorTransformInternal(int displayId, int colorTransformId) {
544         synchronized (mSyncRoot) {
545             LogicalDisplay display = mLogicalDisplays.get(displayId);
546             if (display != null &&
547                     display.getRequestedColorTransformIdLocked() != colorTransformId) {
548                 display.setRequestedColorTransformIdLocked(colorTransformId);
549                 scheduleTraversalLocked(false);
550             }
551         }
552     }
553 
createVirtualDisplayInternal(IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)554     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
555             IMediaProjection projection, int callingUid, String packageName,
556             String name, int width, int height, int densityDpi, Surface surface, int flags) {
557         synchronized (mSyncRoot) {
558             if (mVirtualDisplayAdapter == null) {
559                 Slog.w(TAG, "Rejecting request to create private virtual display "
560                         + "because the virtual display adapter is not available.");
561                 return -1;
562             }
563 
564             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
565                     callback, projection, callingUid, packageName,
566                     name, width, height, densityDpi, surface, flags);
567             if (device == null) {
568                 return -1;
569             }
570 
571             handleDisplayDeviceAddedLocked(device);
572             LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
573             if (display != null) {
574                 return display.getDisplayIdLocked();
575             }
576 
577             // Something weird happened and the logical display was not created.
578             Slog.w(TAG, "Rejecting request to create virtual display "
579                     + "because the logical display was not created.");
580             mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
581             handleDisplayDeviceRemovedLocked(device);
582         }
583         return -1;
584     }
585 
resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)586     private void resizeVirtualDisplayInternal(IBinder appToken,
587             int width, int height, int densityDpi) {
588         synchronized (mSyncRoot) {
589             if (mVirtualDisplayAdapter == null) {
590                 return;
591             }
592 
593             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
594         }
595     }
596 
setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)597     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
598         synchronized (mSyncRoot) {
599             if (mVirtualDisplayAdapter == null) {
600                 return;
601             }
602 
603             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
604         }
605     }
606 
releaseVirtualDisplayInternal(IBinder appToken)607     private void releaseVirtualDisplayInternal(IBinder appToken) {
608         synchronized (mSyncRoot) {
609             if (mVirtualDisplayAdapter == null) {
610                 return;
611             }
612 
613             DisplayDevice device =
614                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
615             if (device != null) {
616                 handleDisplayDeviceRemovedLocked(device);
617             }
618         }
619     }
620 
registerDefaultDisplayAdapter()621     private void registerDefaultDisplayAdapter() {
622         // Register default display adapter.
623         synchronized (mSyncRoot) {
624             registerDisplayAdapterLocked(new LocalDisplayAdapter(
625                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
626         }
627     }
628 
registerAdditionalDisplayAdapters()629     private void registerAdditionalDisplayAdapters() {
630         synchronized (mSyncRoot) {
631             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
632                 registerOverlayDisplayAdapterLocked();
633                 registerWifiDisplayAdapterLocked();
634                 registerVirtualDisplayAdapterLocked();
635             }
636         }
637     }
638 
registerOverlayDisplayAdapterLocked()639     private void registerOverlayDisplayAdapterLocked() {
640         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
641                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
642     }
643 
registerWifiDisplayAdapterLocked()644     private void registerWifiDisplayAdapterLocked() {
645         if (mContext.getResources().getBoolean(
646                 com.android.internal.R.bool.config_enableWifiDisplay)
647                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
648             mWifiDisplayAdapter = new WifiDisplayAdapter(
649                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
650                     mPersistentDataStore);
651             registerDisplayAdapterLocked(mWifiDisplayAdapter);
652         }
653     }
654 
registerVirtualDisplayAdapterLocked()655     private void registerVirtualDisplayAdapterLocked() {
656         mVirtualDisplayAdapter = new VirtualDisplayAdapter(
657                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
658         registerDisplayAdapterLocked(mVirtualDisplayAdapter);
659     }
660 
shouldRegisterNonEssentialDisplayAdaptersLocked()661     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
662         // In safe mode, we disable non-essential display adapters to give the user
663         // an opportunity to fix broken settings or other problems that might affect
664         // system stability.
665         // In only-core mode, we disable non-essential display adapters to minimize
666         // the number of dependencies that are started while in this mode and to
667         // prevent problems that might occur due to the device being encrypted.
668         return !mSafeMode && !mOnlyCore;
669     }
670 
registerDisplayAdapterLocked(DisplayAdapter adapter)671     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
672         mDisplayAdapters.add(adapter);
673         adapter.registerLocked();
674     }
675 
handleDisplayDeviceAdded(DisplayDevice device)676     private void handleDisplayDeviceAdded(DisplayDevice device) {
677         synchronized (mSyncRoot) {
678             handleDisplayDeviceAddedLocked(device);
679         }
680     }
681 
handleDisplayDeviceAddedLocked(DisplayDevice device)682     private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
683         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
684         if (mDisplayDevices.contains(device)) {
685             Slog.w(TAG, "Attempted to add already added display device: " + info);
686             return;
687         }
688 
689         Slog.i(TAG, "Display device added: " + info);
690         device.mDebugLastLoggedDeviceInfo = info;
691 
692         mDisplayDevices.add(device);
693         addLogicalDisplayLocked(device);
694         Runnable work = updateDisplayStateLocked(device);
695         if (work != null) {
696             work.run();
697         }
698         scheduleTraversalLocked(false);
699     }
700 
handleDisplayDeviceChanged(DisplayDevice device)701     private void handleDisplayDeviceChanged(DisplayDevice device) {
702         synchronized (mSyncRoot) {
703             DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
704             if (!mDisplayDevices.contains(device)) {
705                 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
706                 return;
707             }
708 
709             int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
710             if (diff == DisplayDeviceInfo.DIFF_STATE) {
711                 Slog.i(TAG, "Display device changed state: \"" + info.name
712                         + "\", " + Display.stateToString(info.state));
713             } else if (diff != 0) {
714                 Slog.i(TAG, "Display device changed: " + info);
715             }
716             device.mDebugLastLoggedDeviceInfo = info;
717 
718             device.applyPendingDisplayDeviceInfoChangesLocked();
719             if (updateLogicalDisplaysLocked()) {
720                 scheduleTraversalLocked(false);
721             }
722         }
723     }
724 
handleDisplayDeviceRemoved(DisplayDevice device)725     private void handleDisplayDeviceRemoved(DisplayDevice device) {
726         synchronized (mSyncRoot) {
727             handleDisplayDeviceRemovedLocked(device);
728         }
729     }
730 
handleDisplayDeviceRemovedLocked(DisplayDevice device)731     private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
732         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
733         if (!mDisplayDevices.remove(device)) {
734             Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
735             return;
736         }
737 
738         Slog.i(TAG, "Display device removed: " + info);
739         device.mDebugLastLoggedDeviceInfo = info;
740 
741         updateLogicalDisplaysLocked();
742         scheduleTraversalLocked(false);
743     }
744 
applyGlobalDisplayStateLocked(List<Runnable> workQueue)745     private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
746         final int count = mDisplayDevices.size();
747         for (int i = 0; i < count; i++) {
748             DisplayDevice device = mDisplayDevices.get(i);
749             Runnable runnable = updateDisplayStateLocked(device);
750             if (runnable != null) {
751                 workQueue.add(runnable);
752             }
753         }
754     }
755 
updateDisplayStateLocked(DisplayDevice device)756     private Runnable updateDisplayStateLocked(DisplayDevice device) {
757         // Blank or unblank the display immediately to match the state requested
758         // by the display power controller (if known).
759         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
760         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
761             return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
762         }
763         return null;
764     }
765 
766     // Adds a new logical display based on the given display device.
767     // Sends notifications if needed.
addLogicalDisplayLocked(DisplayDevice device)768     private void addLogicalDisplayLocked(DisplayDevice device) {
769         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
770         boolean isDefault = (deviceInfo.flags
771                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
772         if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
773             Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
774             isDefault = false;
775         }
776 
777         if (!isDefault && mSingleDisplayDemoMode) {
778             Slog.i(TAG, "Not creating a logical display for a secondary display "
779                     + " because single display demo mode is enabled: " + deviceInfo);
780             return;
781         }
782 
783         final int displayId = assignDisplayIdLocked(isDefault);
784         final int layerStack = assignLayerStackLocked(displayId);
785 
786         LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
787         display.updateLocked(mDisplayDevices);
788         if (!display.isValidLocked()) {
789             // This should never happen currently.
790             Slog.w(TAG, "Ignoring display device because the logical display "
791                     + "created from it was not considered valid: " + deviceInfo);
792             return;
793         }
794 
795         mLogicalDisplays.put(displayId, display);
796 
797         // Wake up waitForDefaultDisplay.
798         if (isDefault) {
799             mSyncRoot.notifyAll();
800         }
801 
802         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
803     }
804 
assignDisplayIdLocked(boolean isDefault)805     private int assignDisplayIdLocked(boolean isDefault) {
806         return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
807     }
808 
assignLayerStackLocked(int displayId)809     private int assignLayerStackLocked(int displayId) {
810         // Currently layer stacks and display ids are the same.
811         // This need not be the case.
812         return displayId;
813     }
814 
815     // Updates all existing logical displays given the current set of display devices.
816     // Removes invalid logical displays.
817     // Sends notifications if needed.
updateLogicalDisplaysLocked()818     private boolean updateLogicalDisplaysLocked() {
819         boolean changed = false;
820         for (int i = mLogicalDisplays.size(); i-- > 0; ) {
821             final int displayId = mLogicalDisplays.keyAt(i);
822             LogicalDisplay display = mLogicalDisplays.valueAt(i);
823 
824             mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
825             display.updateLocked(mDisplayDevices);
826             if (!display.isValidLocked()) {
827                 mLogicalDisplays.removeAt(i);
828                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
829                 changed = true;
830             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
831                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
832                 changed = true;
833             }
834         }
835         return changed;
836     }
837 
performTraversalInTransactionLocked()838     private void performTraversalInTransactionLocked() {
839         // Clear all viewports before configuring displays so that we can keep
840         // track of which ones we have configured.
841         clearViewportsLocked();
842 
843         // Configure each display device.
844         final int count = mDisplayDevices.size();
845         for (int i = 0; i < count; i++) {
846             DisplayDevice device = mDisplayDevices.get(i);
847             configureDisplayInTransactionLocked(device);
848             device.performTraversalInTransactionLocked();
849         }
850 
851         // Tell the input system about these new viewports.
852         if (mInputManagerInternal != null) {
853             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
854         }
855     }
856 
setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, boolean inTraversal)857     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
858             float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
859         synchronized (mSyncRoot) {
860             LogicalDisplay display = mLogicalDisplays.get(displayId);
861             if (display == null) {
862                 return;
863             }
864             if (display.hasContentLocked() != hasContent) {
865                 if (DEBUG) {
866                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
867                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
868                 }
869 
870                 display.setHasContentLocked(hasContent);
871                 scheduleTraversalLocked(inTraversal);
872             }
873             if (requestedModeId == 0 && requestedRefreshRate != 0) {
874                 // Scan supported modes returned by display.getInfo() to find a mode with the same
875                 // size as the default display mode but with the specified refresh rate instead.
876                 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
877                         requestedRefreshRate);
878             }
879             if (display.getRequestedModeIdLocked() != requestedModeId) {
880                 if (DEBUG) {
881                     Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
882                 }
883                 display.setRequestedModeIdLocked(requestedModeId);
884                 scheduleTraversalLocked(inTraversal);
885             }
886         }
887     }
888 
setDisplayOffsetsInternal(int displayId, int x, int y)889     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
890         synchronized (mSyncRoot) {
891             LogicalDisplay display = mLogicalDisplays.get(displayId);
892             if (display == null) {
893                 return;
894             }
895             if (display.getDisplayOffsetXLocked() != x
896                     || display.getDisplayOffsetYLocked() != y) {
897                 if (DEBUG) {
898                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
899                             + x + ", " + y + ")");
900                 }
901                 display.setDisplayOffsetsLocked(x, y);
902                 scheduleTraversalLocked(false);
903             }
904         }
905     }
906 
clearViewportsLocked()907     private void clearViewportsLocked() {
908         mDefaultViewport.valid = false;
909         mExternalTouchViewport.valid = false;
910     }
911 
configureDisplayInTransactionLocked(DisplayDevice device)912     private void configureDisplayInTransactionLocked(DisplayDevice device) {
913         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
914         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
915 
916         // Find the logical display that the display device is showing.
917         // Certain displays only ever show their own content.
918         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
919         if (!ownContent) {
920             if (display != null && !display.hasContentLocked()) {
921                 // If the display does not have any content of its own, then
922                 // automatically mirror the default logical display contents.
923                 display = null;
924             }
925             if (display == null) {
926                 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
927             }
928         }
929 
930         // Apply the logical display configuration to the display device.
931         if (display == null) {
932             // TODO: no logical display for the device, blank it
933             Slog.w(TAG, "Missing logical display to use for physical display device: "
934                     + device.getDisplayDeviceInfoLocked());
935             return;
936         }
937         display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
938 
939         // Update the viewports if needed.
940         if (!mDefaultViewport.valid
941                 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
942             setViewportLocked(mDefaultViewport, display, device);
943         }
944         if (!mExternalTouchViewport.valid
945                 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
946             setViewportLocked(mExternalTouchViewport, display, device);
947         }
948     }
949 
setViewportLocked(DisplayViewport viewport, LogicalDisplay display, DisplayDevice device)950     private static void setViewportLocked(DisplayViewport viewport,
951             LogicalDisplay display, DisplayDevice device) {
952         viewport.valid = true;
953         viewport.displayId = display.getDisplayIdLocked();
954         device.populateViewportLocked(viewport);
955     }
956 
findLogicalDisplayForDeviceLocked(DisplayDevice device)957     private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
958         final int count = mLogicalDisplays.size();
959         for (int i = 0; i < count; i++) {
960             LogicalDisplay display = mLogicalDisplays.valueAt(i);
961             if (display.getPrimaryDisplayDeviceLocked() == device) {
962                 return display;
963             }
964         }
965         return null;
966     }
967 
sendDisplayEventLocked(int displayId, int event)968     private void sendDisplayEventLocked(int displayId, int event) {
969         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
970         mHandler.sendMessage(msg);
971     }
972 
973     // Requests that performTraversalsInTransactionFromWindowManager be called at a
974     // later time to apply changes to surfaces and displays.
scheduleTraversalLocked(boolean inTraversal)975     private void scheduleTraversalLocked(boolean inTraversal) {
976         if (!mPendingTraversal && mWindowManagerInternal != null) {
977             mPendingTraversal = true;
978             if (!inTraversal) {
979                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
980             }
981         }
982     }
983 
984     // Runs on Handler thread.
985     // Delivers display event notifications to callbacks.
deliverDisplayEvent(int displayId, int event)986     private void deliverDisplayEvent(int displayId, int event) {
987         if (DEBUG) {
988             Slog.d(TAG, "Delivering display event: displayId="
989                     + displayId + ", event=" + event);
990         }
991 
992         // Grab the lock and copy the callbacks.
993         final int count;
994         synchronized (mSyncRoot) {
995             count = mCallbacks.size();
996             mTempCallbacks.clear();
997             for (int i = 0; i < count; i++) {
998                 mTempCallbacks.add(mCallbacks.valueAt(i));
999             }
1000         }
1001 
1002         // After releasing the lock, send the notifications out.
1003         for (int i = 0; i < count; i++) {
1004             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1005         }
1006         mTempCallbacks.clear();
1007     }
1008 
getProjectionService()1009     private IMediaProjectionManager getProjectionService() {
1010         if (mProjectionService == null) {
1011             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
1012             mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
1013         }
1014         return mProjectionService;
1015     }
1016 
dumpInternal(PrintWriter pw)1017     private void dumpInternal(PrintWriter pw) {
1018         pw.println("DISPLAY MANAGER (dumpsys display)");
1019 
1020         synchronized (mSyncRoot) {
1021             pw.println("  mOnlyCode=" + mOnlyCore);
1022             pw.println("  mSafeMode=" + mSafeMode);
1023             pw.println("  mPendingTraversal=" + mPendingTraversal);
1024             pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
1025             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1026             pw.println("  mDefaultViewport=" + mDefaultViewport);
1027             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
1028             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
1029             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
1030 
1031             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
1032             ipw.increaseIndent();
1033 
1034             pw.println();
1035             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
1036             for (DisplayAdapter adapter : mDisplayAdapters) {
1037                 pw.println("  " + adapter.getName());
1038                 adapter.dumpLocked(ipw);
1039             }
1040 
1041             pw.println();
1042             pw.println("Display Devices: size=" + mDisplayDevices.size());
1043             for (DisplayDevice device : mDisplayDevices) {
1044                 pw.println("  " + device.getDisplayDeviceInfoLocked());
1045                 device.dumpLocked(ipw);
1046             }
1047 
1048             final int logicalDisplayCount = mLogicalDisplays.size();
1049             pw.println();
1050             pw.println("Logical Displays: size=" + logicalDisplayCount);
1051             for (int i = 0; i < logicalDisplayCount; i++) {
1052                 int displayId = mLogicalDisplays.keyAt(i);
1053                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1054                 pw.println("  Display " + displayId + ":");
1055                 display.dumpLocked(ipw);
1056             }
1057 
1058             final int callbackCount = mCallbacks.size();
1059             pw.println();
1060             pw.println("Callbacks: size=" + callbackCount);
1061             for (int i = 0; i < callbackCount; i++) {
1062                 CallbackRecord callback = mCallbacks.valueAt(i);
1063                 pw.println("  " + i + ": mPid=" + callback.mPid
1064                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
1065             }
1066 
1067             if (mDisplayPowerController != null) {
1068                 mDisplayPowerController.dump(pw);
1069             }
1070         }
1071     }
1072 
1073     /**
1074      * This is the object that everything in the display manager locks on.
1075      * We make it an inner class within the {@link DisplayManagerService} to so that it is
1076      * clear that the object belongs to the display manager service and that it is
1077      * a unique object with a special purpose.
1078      */
1079     public static final class SyncRoot {
1080     }
1081 
1082     private final class DisplayManagerHandler extends Handler {
DisplayManagerHandler(Looper looper)1083         public DisplayManagerHandler(Looper looper) {
1084             super(looper, null, true /*async*/);
1085         }
1086 
1087         @Override
handleMessage(Message msg)1088         public void handleMessage(Message msg) {
1089             switch (msg.what) {
1090                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
1091                     registerDefaultDisplayAdapter();
1092                     break;
1093 
1094                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1095                     registerAdditionalDisplayAdapters();
1096                     break;
1097 
1098                 case MSG_DELIVER_DISPLAY_EVENT:
1099                     deliverDisplayEvent(msg.arg1, msg.arg2);
1100                     break;
1101 
1102                 case MSG_REQUEST_TRAVERSAL:
1103                     mWindowManagerInternal.requestTraversalFromDisplayManager();
1104                     break;
1105 
1106                 case MSG_UPDATE_VIEWPORT: {
1107                     synchronized (mSyncRoot) {
1108                         mTempDefaultViewport.copyFrom(mDefaultViewport);
1109                         mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1110                     }
1111                     mInputManagerInternal.setDisplayViewports(
1112                             mTempDefaultViewport, mTempExternalTouchViewport);
1113                     break;
1114                 }
1115             }
1116         }
1117     }
1118 
1119     private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1120         @Override
onDisplayDeviceEvent(DisplayDevice device, int event)1121         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1122             switch (event) {
1123                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1124                     handleDisplayDeviceAdded(device);
1125                     break;
1126 
1127                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1128                     handleDisplayDeviceChanged(device);
1129                     break;
1130 
1131                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1132                     handleDisplayDeviceRemoved(device);
1133                     break;
1134             }
1135         }
1136 
1137         @Override
onTraversalRequested()1138         public void onTraversalRequested() {
1139             synchronized (mSyncRoot) {
1140                 scheduleTraversalLocked(false);
1141             }
1142         }
1143     }
1144 
1145     private final class CallbackRecord implements DeathRecipient {
1146         public final int mPid;
1147         private final IDisplayManagerCallback mCallback;
1148 
1149         public boolean mWifiDisplayScanRequested;
1150 
CallbackRecord(int pid, IDisplayManagerCallback callback)1151         public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1152             mPid = pid;
1153             mCallback = callback;
1154         }
1155 
1156         @Override
binderDied()1157         public void binderDied() {
1158             if (DEBUG) {
1159                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1160             }
1161             onCallbackDied(this);
1162         }
1163 
notifyDisplayEventAsync(int displayId, int event)1164         public void notifyDisplayEventAsync(int displayId, int event) {
1165             try {
1166                 mCallback.onDisplayEvent(displayId, event);
1167             } catch (RemoteException ex) {
1168                 Slog.w(TAG, "Failed to notify process "
1169                         + mPid + " that displays changed, assuming it died.", ex);
1170                 binderDied();
1171             }
1172         }
1173     }
1174 
1175     private final class BinderService extends IDisplayManager.Stub {
1176         /**
1177          * Returns information about the specified logical display.
1178          *
1179          * @param displayId The logical display id.
1180          * @return The logical display info, or null if the display does not exist.  The
1181          * returned object must be treated as immutable.
1182          */
1183         @Override // Binder call
getDisplayInfo(int displayId)1184         public DisplayInfo getDisplayInfo(int displayId) {
1185             final int callingUid = Binder.getCallingUid();
1186             final long token = Binder.clearCallingIdentity();
1187             try {
1188                 return getDisplayInfoInternal(displayId, callingUid);
1189             } finally {
1190                 Binder.restoreCallingIdentity(token);
1191             }
1192         }
1193 
1194         /**
1195          * Returns the list of all display ids.
1196          */
1197         @Override // Binder call
getDisplayIds()1198         public int[] getDisplayIds() {
1199             final int callingUid = Binder.getCallingUid();
1200             final long token = Binder.clearCallingIdentity();
1201             try {
1202                 return getDisplayIdsInternal(callingUid);
1203             } finally {
1204                 Binder.restoreCallingIdentity(token);
1205             }
1206         }
1207 
1208         @Override // Binder call
registerCallback(IDisplayManagerCallback callback)1209         public void registerCallback(IDisplayManagerCallback callback) {
1210             if (callback == null) {
1211                 throw new IllegalArgumentException("listener must not be null");
1212             }
1213 
1214             final int callingPid = Binder.getCallingPid();
1215             final long token = Binder.clearCallingIdentity();
1216             try {
1217                 registerCallbackInternal(callback, callingPid);
1218             } finally {
1219                 Binder.restoreCallingIdentity(token);
1220             }
1221         }
1222 
1223         @Override // Binder call
startWifiDisplayScan()1224         public void startWifiDisplayScan() {
1225             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1226                     "Permission required to start wifi display scans");
1227 
1228             final int callingPid = Binder.getCallingPid();
1229             final long token = Binder.clearCallingIdentity();
1230             try {
1231                 startWifiDisplayScanInternal(callingPid);
1232             } finally {
1233                 Binder.restoreCallingIdentity(token);
1234             }
1235         }
1236 
1237         @Override // Binder call
stopWifiDisplayScan()1238         public void stopWifiDisplayScan() {
1239             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1240                     "Permission required to stop wifi display scans");
1241 
1242             final int callingPid = Binder.getCallingPid();
1243             final long token = Binder.clearCallingIdentity();
1244             try {
1245                 stopWifiDisplayScanInternal(callingPid);
1246             } finally {
1247                 Binder.restoreCallingIdentity(token);
1248             }
1249         }
1250 
1251         @Override // Binder call
connectWifiDisplay(String address)1252         public void connectWifiDisplay(String address) {
1253             if (address == null) {
1254                 throw new IllegalArgumentException("address must not be null");
1255             }
1256             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1257                     "Permission required to connect to a wifi display");
1258 
1259             final long token = Binder.clearCallingIdentity();
1260             try {
1261                 connectWifiDisplayInternal(address);
1262             } finally {
1263                 Binder.restoreCallingIdentity(token);
1264             }
1265         }
1266 
1267         @Override // Binder call
disconnectWifiDisplay()1268         public void disconnectWifiDisplay() {
1269             // This request does not require special permissions.
1270             // Any app can request disconnection from the currently active wifi display.
1271             // This exception should no longer be needed once wifi display control moves
1272             // to the media router service.
1273 
1274             final long token = Binder.clearCallingIdentity();
1275             try {
1276                 disconnectWifiDisplayInternal();
1277             } finally {
1278                 Binder.restoreCallingIdentity(token);
1279             }
1280         }
1281 
1282         @Override // Binder call
renameWifiDisplay(String address, String alias)1283         public void renameWifiDisplay(String address, String alias) {
1284             if (address == null) {
1285                 throw new IllegalArgumentException("address must not be null");
1286             }
1287             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1288                     "Permission required to rename to a wifi display");
1289 
1290             final long token = Binder.clearCallingIdentity();
1291             try {
1292                 renameWifiDisplayInternal(address, alias);
1293             } finally {
1294                 Binder.restoreCallingIdentity(token);
1295             }
1296         }
1297 
1298         @Override // Binder call
forgetWifiDisplay(String address)1299         public void forgetWifiDisplay(String address) {
1300             if (address == null) {
1301                 throw new IllegalArgumentException("address must not be null");
1302             }
1303             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1304                     "Permission required to forget to a wifi display");
1305 
1306             final long token = Binder.clearCallingIdentity();
1307             try {
1308                 forgetWifiDisplayInternal(address);
1309             } finally {
1310                 Binder.restoreCallingIdentity(token);
1311             }
1312         }
1313 
1314         @Override // Binder call
pauseWifiDisplay()1315         public void pauseWifiDisplay() {
1316             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1317                     "Permission required to pause a wifi display session");
1318 
1319             final long token = Binder.clearCallingIdentity();
1320             try {
1321                 pauseWifiDisplayInternal();
1322             } finally {
1323                 Binder.restoreCallingIdentity(token);
1324             }
1325         }
1326 
1327         @Override // Binder call
resumeWifiDisplay()1328         public void resumeWifiDisplay() {
1329             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1330                     "Permission required to resume a wifi display session");
1331 
1332             final long token = Binder.clearCallingIdentity();
1333             try {
1334                 resumeWifiDisplayInternal();
1335             } finally {
1336                 Binder.restoreCallingIdentity(token);
1337             }
1338         }
1339 
1340         @Override // Binder call
getWifiDisplayStatus()1341         public WifiDisplayStatus getWifiDisplayStatus() {
1342             // This request does not require special permissions.
1343             // Any app can get information about available wifi displays.
1344 
1345             final long token = Binder.clearCallingIdentity();
1346             try {
1347                 return getWifiDisplayStatusInternal();
1348             } finally {
1349                 Binder.restoreCallingIdentity(token);
1350             }
1351         }
1352 
1353         @Override // Binder call
requestColorTransform(int displayId, int colorTransformId)1354         public void requestColorTransform(int displayId, int colorTransformId) {
1355             mContext.enforceCallingOrSelfPermission(
1356                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM,
1357                     "Permission required to change the display color transform");
1358             final long token = Binder.clearCallingIdentity();
1359             try {
1360                 requestColorTransformInternal(displayId, colorTransformId);
1361             } finally {
1362                 Binder.restoreCallingIdentity(token);
1363             }
1364         }
1365 
1366         @Override // Binder call
createVirtualDisplay(IVirtualDisplayCallback callback, IMediaProjection projection, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)1367         public int createVirtualDisplay(IVirtualDisplayCallback callback,
1368                 IMediaProjection projection, String packageName, String name,
1369                 int width, int height, int densityDpi, Surface surface, int flags) {
1370             final int callingUid = Binder.getCallingUid();
1371             if (!validatePackageName(callingUid, packageName)) {
1372                 throw new SecurityException("packageName must match the calling uid");
1373             }
1374             if (callback == null) {
1375                 throw new IllegalArgumentException("appToken must not be null");
1376             }
1377             if (TextUtils.isEmpty(name)) {
1378                 throw new IllegalArgumentException("name must be non-null and non-empty");
1379             }
1380             if (width <= 0 || height <= 0 || densityDpi <= 0) {
1381                 throw new IllegalArgumentException("width, height, and densityDpi must be "
1382                         + "greater than 0");
1383             }
1384 
1385             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1386                 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1387             }
1388             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
1389                 flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
1390             }
1391 
1392             if (projection != null) {
1393                 try {
1394                     if (!getProjectionService().isValidMediaProjection(projection)) {
1395                         throw new SecurityException("Invalid media projection");
1396                     }
1397                     flags = projection.applyVirtualDisplayFlags(flags);
1398                 } catch (RemoteException e) {
1399                     throw new SecurityException("unable to validate media projection or flags");
1400                 }
1401             }
1402 
1403             if (callingUid != Process.SYSTEM_UID &&
1404                     (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
1405                 if (!canProjectVideo(projection)) {
1406                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1407                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1408                             + "MediaProjection token in order to create a screen sharing virtual "
1409                             + "display.");
1410                 }
1411             }
1412             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1413                 if (!canProjectSecureVideo(projection)) {
1414                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1415                             + "or an appropriate MediaProjection token to create a "
1416                             + "secure virtual display.");
1417                 }
1418             }
1419 
1420             final long token = Binder.clearCallingIdentity();
1421             try {
1422                 return createVirtualDisplayInternal(callback, projection, callingUid,
1423                         packageName, name, width, height, densityDpi, surface, flags);
1424             } finally {
1425                 Binder.restoreCallingIdentity(token);
1426             }
1427         }
1428 
1429         @Override // Binder call
resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)1430         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
1431                 int width, int height, int densityDpi) {
1432             final long token = Binder.clearCallingIdentity();
1433             try {
1434                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
1435             } finally {
1436                 Binder.restoreCallingIdentity(token);
1437             }
1438         }
1439 
1440         @Override // Binder call
setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)1441         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
1442             final long token = Binder.clearCallingIdentity();
1443             try {
1444                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
1445             } finally {
1446                 Binder.restoreCallingIdentity(token);
1447             }
1448         }
1449 
1450         @Override // Binder call
releaseVirtualDisplay(IVirtualDisplayCallback callback)1451         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
1452             final long token = Binder.clearCallingIdentity();
1453             try {
1454                 releaseVirtualDisplayInternal(callback.asBinder());
1455             } finally {
1456                 Binder.restoreCallingIdentity(token);
1457             }
1458         }
1459 
1460         @Override // Binder call
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1461         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1462             if (mContext == null
1463                     || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1464                             != PackageManager.PERMISSION_GRANTED) {
1465                 pw.println("Permission Denial: can't dump DisplayManager from from pid="
1466                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1467                 return;
1468             }
1469 
1470             final long token = Binder.clearCallingIdentity();
1471             try {
1472                 dumpInternal(pw);
1473             } finally {
1474                 Binder.restoreCallingIdentity(token);
1475             }
1476         }
1477 
validatePackageName(int uid, String packageName)1478         private boolean validatePackageName(int uid, String packageName) {
1479             if (packageName != null) {
1480                 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1481                 if (packageNames != null) {
1482                     for (String n : packageNames) {
1483                         if (n.equals(packageName)) {
1484                             return true;
1485                         }
1486                     }
1487                 }
1488             }
1489             return false;
1490         }
1491 
canProjectVideo(IMediaProjection projection)1492         private boolean canProjectVideo(IMediaProjection projection) {
1493             if (projection != null) {
1494                 try {
1495                     if (projection.canProjectVideo()) {
1496                         return true;
1497                     }
1498                 } catch (RemoteException e) {
1499                     Slog.e(TAG, "Unable to query projection service for permissions", e);
1500                 }
1501             }
1502             if (mContext.checkCallingPermission(
1503                     android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1504                     == PackageManager.PERMISSION_GRANTED) {
1505                 return true;
1506             }
1507             return canProjectSecureVideo(projection);
1508         }
1509 
canProjectSecureVideo(IMediaProjection projection)1510         private boolean canProjectSecureVideo(IMediaProjection projection) {
1511             if (projection != null) {
1512                 try {
1513                     if (projection.canProjectSecureVideo()){
1514                         return true;
1515                     }
1516                 } catch (RemoteException e) {
1517                     Slog.e(TAG, "Unable to query projection service for permissions", e);
1518                 }
1519             }
1520             return mContext.checkCallingPermission(
1521                     android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1522                     == PackageManager.PERMISSION_GRANTED;
1523         }
1524     }
1525 
1526     private final class LocalService extends DisplayManagerInternal {
1527         @Override
initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)1528         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
1529                 SensorManager sensorManager) {
1530             synchronized (mSyncRoot) {
1531                 DisplayBlanker blanker = new DisplayBlanker() {
1532                     @Override
1533                     public void requestDisplayState(int state, int brightness) {
1534                         // The order of operations is important for legacy reasons.
1535                         if (state == Display.STATE_OFF) {
1536                             requestGlobalDisplayStateInternal(state, brightness);
1537                         }
1538 
1539                         callbacks.onDisplayStateChange(state);
1540 
1541                         if (state != Display.STATE_OFF) {
1542                             requestGlobalDisplayStateInternal(state, brightness);
1543                         }
1544                     }
1545                 };
1546                 mDisplayPowerController = new DisplayPowerController(
1547                         mContext, callbacks, handler, sensorManager, blanker);
1548             }
1549         }
1550 
1551         @Override
requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)1552         public boolean requestPowerState(DisplayPowerRequest request,
1553                 boolean waitForNegativeProximity) {
1554             return mDisplayPowerController.requestPowerState(request,
1555                     waitForNegativeProximity);
1556         }
1557 
1558         @Override
isProximitySensorAvailable()1559         public boolean isProximitySensorAvailable() {
1560             return mDisplayPowerController.isProximitySensorAvailable();
1561         }
1562 
1563         @Override
getDisplayInfo(int displayId)1564         public DisplayInfo getDisplayInfo(int displayId) {
1565             return getDisplayInfoInternal(displayId, Process.myUid());
1566         }
1567 
1568         @Override
registerDisplayTransactionListener(DisplayTransactionListener listener)1569         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1570             if (listener == null) {
1571                 throw new IllegalArgumentException("listener must not be null");
1572             }
1573 
1574             registerDisplayTransactionListenerInternal(listener);
1575         }
1576 
1577         @Override
unregisterDisplayTransactionListener(DisplayTransactionListener listener)1578         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1579             if (listener == null) {
1580                 throw new IllegalArgumentException("listener must not be null");
1581             }
1582 
1583             unregisterDisplayTransactionListenerInternal(listener);
1584         }
1585 
1586         @Override
setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)1587         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1588             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1589         }
1590 
1591         @Override
performTraversalInTransactionFromWindowManager()1592         public void performTraversalInTransactionFromWindowManager() {
1593             performTraversalInTransactionFromWindowManagerInternal();
1594         }
1595 
1596         @Override
setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, boolean inTraversal)1597         public void setDisplayProperties(int displayId, boolean hasContent,
1598                 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
1599             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
1600                     requestedMode, inTraversal);
1601         }
1602 
1603         @Override
setDisplayOffsets(int displayId, int x, int y)1604         public void setDisplayOffsets(int displayId, int x, int y) {
1605             setDisplayOffsetsInternal(displayId, x, y);
1606         }
1607     }
1608 }
1609