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