DisplayManagerService.java revision c39d47a8e7c74bd539104b0efab898ef6fc43ddf
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.IVirtualDisplayCallbacks;
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(IVirtualDisplayCallbacks callbacks,
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                    callbacks, 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(callbacks.asBinder());
521            handleDisplayDeviceRemovedLocked(device);
522        }
523        return -1;
524    }
525
526    private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
527        synchronized (mSyncRoot) {
528            if (mVirtualDisplayAdapter == null) {
529                return;
530            }
531
532            mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
533        }
534    }
535
536    private void releaseVirtualDisplayInternal(IBinder appToken) {
537        synchronized (mSyncRoot) {
538            if (mVirtualDisplayAdapter == null) {
539                return;
540            }
541
542            DisplayDevice device =
543                    mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
544            if (device != null) {
545                handleDisplayDeviceRemovedLocked(device);
546            }
547        }
548    }
549
550    private void registerDefaultDisplayAdapter() {
551        // Register default display adapter.
552        synchronized (mSyncRoot) {
553            registerDisplayAdapterLocked(new LocalDisplayAdapter(
554                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
555        }
556    }
557
558    private void registerAdditionalDisplayAdapters() {
559        synchronized (mSyncRoot) {
560            if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
561                registerOverlayDisplayAdapterLocked();
562                registerWifiDisplayAdapterLocked();
563                registerVirtualDisplayAdapterLocked();
564            }
565        }
566    }
567
568    private void registerOverlayDisplayAdapterLocked() {
569        registerDisplayAdapterLocked(new OverlayDisplayAdapter(
570                mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
571    }
572
573    private void registerWifiDisplayAdapterLocked() {
574        if (mContext.getResources().getBoolean(
575                com.android.internal.R.bool.config_enableWifiDisplay)
576                || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
577            mWifiDisplayAdapter = new WifiDisplayAdapter(
578                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
579                    mPersistentDataStore);
580            registerDisplayAdapterLocked(mWifiDisplayAdapter);
581        }
582    }
583
584    private void registerVirtualDisplayAdapterLocked() {
585        mVirtualDisplayAdapter = new VirtualDisplayAdapter(
586                mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
587        registerDisplayAdapterLocked(mVirtualDisplayAdapter);
588    }
589
590    private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
591        // In safe mode, we disable non-essential display adapters to give the user
592        // an opportunity to fix broken settings or other problems that might affect
593        // system stability.
594        // In only-core mode, we disable non-essential display adapters to minimize
595        // the number of dependencies that are started while in this mode and to
596        // prevent problems that might occur due to the device being encrypted.
597        return !mSafeMode && !mOnlyCore;
598    }
599
600    private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
601        mDisplayAdapters.add(adapter);
602        adapter.registerLocked();
603    }
604
605    private void handleDisplayDeviceAdded(DisplayDevice device) {
606        synchronized (mSyncRoot) {
607            handleDisplayDeviceAddedLocked(device);
608        }
609    }
610
611    private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
612        if (mDisplayDevices.contains(device)) {
613            Slog.w(TAG, "Attempted to add already added display device: "
614                    + device.getDisplayDeviceInfoLocked());
615            return;
616        }
617
618        Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
619
620        mDisplayDevices.add(device);
621        addLogicalDisplayLocked(device);
622        updateDisplayStateLocked(device);
623        scheduleTraversalLocked(false);
624    }
625
626    private void handleDisplayDeviceChanged(DisplayDevice device) {
627        synchronized (mSyncRoot) {
628            if (!mDisplayDevices.contains(device)) {
629                Slog.w(TAG, "Attempted to change non-existent display device: "
630                        + device.getDisplayDeviceInfoLocked());
631                return;
632            }
633
634            Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
635
636            device.applyPendingDisplayDeviceInfoChangesLocked();
637            if (updateLogicalDisplaysLocked()) {
638                scheduleTraversalLocked(false);
639            }
640        }
641    }
642
643    private void handleDisplayDeviceRemoved(DisplayDevice device) {
644        synchronized (mSyncRoot) {
645            handleDisplayDeviceRemovedLocked(device);
646        }
647    }
648    private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
649        if (!mDisplayDevices.remove(device)) {
650            Slog.w(TAG, "Attempted to remove non-existent display device: "
651                    + device.getDisplayDeviceInfoLocked());
652            return;
653        }
654
655        Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
656
657        updateLogicalDisplaysLocked();
658        scheduleTraversalLocked(false);
659    }
660
661    private void updateGlobalDisplayStateLocked() {
662        final int count = mDisplayDevices.size();
663        for (int i = 0; i < count; i++) {
664            DisplayDevice device = mDisplayDevices.get(i);
665            updateDisplayStateLocked(device);
666        }
667    }
668
669    private void updateDisplayStateLocked(DisplayDevice device) {
670        // Blank or unblank the display immediately to match the state requested
671        // by the display power controller (if known).
672        DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
673        if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
674            device.requestDisplayStateLocked(mGlobalDisplayState);
675        }
676    }
677
678    // Adds a new logical display based on the given display device.
679    // Sends notifications if needed.
680    private void addLogicalDisplayLocked(DisplayDevice device) {
681        DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
682        boolean isDefault = (deviceInfo.flags
683                & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
684        if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
685            Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
686            isDefault = false;
687        }
688
689        if (!isDefault && mSingleDisplayDemoMode) {
690            Slog.i(TAG, "Not creating a logical display for a secondary display "
691                    + " because single display demo mode is enabled: " + deviceInfo);
692            return;
693        }
694
695        final int displayId = assignDisplayIdLocked(isDefault);
696        final int layerStack = assignLayerStackLocked(displayId);
697
698        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
699        display.updateLocked(mDisplayDevices);
700        if (!display.isValidLocked()) {
701            // This should never happen currently.
702            Slog.w(TAG, "Ignoring display device because the logical display "
703                    + "created from it was not considered valid: " + deviceInfo);
704            return;
705        }
706
707        mLogicalDisplays.put(displayId, display);
708
709        // Wake up waitForDefaultDisplay.
710        if (isDefault) {
711            mSyncRoot.notifyAll();
712        }
713
714        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
715    }
716
717    private int assignDisplayIdLocked(boolean isDefault) {
718        return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
719    }
720
721    private int assignLayerStackLocked(int displayId) {
722        // Currently layer stacks and display ids are the same.
723        // This need not be the case.
724        return displayId;
725    }
726
727    // Updates all existing logical displays given the current set of display devices.
728    // Removes invalid logical displays.
729    // Sends notifications if needed.
730    private boolean updateLogicalDisplaysLocked() {
731        boolean changed = false;
732        for (int i = mLogicalDisplays.size(); i-- > 0; ) {
733            final int displayId = mLogicalDisplays.keyAt(i);
734            LogicalDisplay display = mLogicalDisplays.valueAt(i);
735
736            mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
737            display.updateLocked(mDisplayDevices);
738            if (!display.isValidLocked()) {
739                mLogicalDisplays.removeAt(i);
740                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
741                changed = true;
742            } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
743                sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
744                changed = true;
745            }
746        }
747        return changed;
748    }
749
750    private void performTraversalInTransactionLocked() {
751        // Clear all viewports before configuring displays so that we can keep
752        // track of which ones we have configured.
753        clearViewportsLocked();
754
755        // Configure each display device.
756        final int count = mDisplayDevices.size();
757        for (int i = 0; i < count; i++) {
758            DisplayDevice device = mDisplayDevices.get(i);
759            configureDisplayInTransactionLocked(device);
760            device.performTraversalInTransactionLocked();
761        }
762
763        // Tell the input system about these new viewports.
764        if (mInputManagerInternal != null) {
765            mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
766        }
767    }
768
769    private void setDisplayHasContentInternal(int displayId, boolean hasContent,
770            boolean inTraversal) {
771        synchronized (mSyncRoot) {
772            LogicalDisplay display = mLogicalDisplays.get(displayId);
773            if (display != null && display.hasContentLocked() != hasContent) {
774                if (DEBUG) {
775                    Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
776                            + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
777                }
778
779                display.setHasContentLocked(hasContent);
780                scheduleTraversalLocked(inTraversal);
781            }
782        }
783    }
784
785    private void clearViewportsLocked() {
786        mDefaultViewport.valid = false;
787        mExternalTouchViewport.valid = false;
788    }
789
790    private void configureDisplayInTransactionLocked(DisplayDevice device) {
791        final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
792        final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
793
794        // Find the logical display that the display device is showing.
795        // Certain displays only ever show their own content.
796        LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
797        if (!ownContent) {
798            if (display != null && !display.hasContentLocked()) {
799                // If the display does not have any content of its own, then
800                // automatically mirror the default logical display contents.
801                display = null;
802            }
803            if (display == null) {
804                display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
805            }
806        }
807
808        // Apply the logical display configuration to the display device.
809        if (display == null) {
810            // TODO: no logical display for the device, blank it
811            Slog.w(TAG, "Missing logical display to use for physical display device: "
812                    + device.getDisplayDeviceInfoLocked());
813            return;
814        }
815        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
816
817        // Update the viewports if needed.
818        if (!mDefaultViewport.valid
819                && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
820            setViewportLocked(mDefaultViewport, display, device);
821        }
822        if (!mExternalTouchViewport.valid
823                && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
824            setViewportLocked(mExternalTouchViewport, display, device);
825        }
826    }
827
828    private static void setViewportLocked(DisplayViewport viewport,
829            LogicalDisplay display, DisplayDevice device) {
830        viewport.valid = true;
831        viewport.displayId = display.getDisplayIdLocked();
832        device.populateViewportLocked(viewport);
833    }
834
835    private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
836        final int count = mLogicalDisplays.size();
837        for (int i = 0; i < count; i++) {
838            LogicalDisplay display = mLogicalDisplays.valueAt(i);
839            if (display.getPrimaryDisplayDeviceLocked() == device) {
840                return display;
841            }
842        }
843        return null;
844    }
845
846    private void sendDisplayEventLocked(int displayId, int event) {
847        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
848        mHandler.sendMessage(msg);
849    }
850
851    // Requests that performTraversalsInTransactionFromWindowManager be called at a
852    // later time to apply changes to surfaces and displays.
853    private void scheduleTraversalLocked(boolean inTraversal) {
854        if (!mPendingTraversal && mWindowManagerInternal != null) {
855            mPendingTraversal = true;
856            if (!inTraversal) {
857                mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
858            }
859        }
860    }
861
862    // Runs on Handler thread.
863    // Delivers display event notifications to callbacks.
864    private void deliverDisplayEvent(int displayId, int event) {
865        if (DEBUG) {
866            Slog.d(TAG, "Delivering display event: displayId="
867                    + displayId + ", event=" + event);
868        }
869
870        // Grab the lock and copy the callbacks.
871        final int count;
872        synchronized (mSyncRoot) {
873            count = mCallbacks.size();
874            mTempCallbacks.clear();
875            for (int i = 0; i < count; i++) {
876                mTempCallbacks.add(mCallbacks.valueAt(i));
877            }
878        }
879
880        // After releasing the lock, send the notifications out.
881        for (int i = 0; i < count; i++) {
882            mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
883        }
884        mTempCallbacks.clear();
885    }
886
887    private IMediaProjectionManager getProjectionService() {
888        if (mProjectionService == null) {
889            IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
890            mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
891        }
892        return mProjectionService;
893    }
894
895    private void dumpInternal(PrintWriter pw) {
896        pw.println("DISPLAY MANAGER (dumpsys display)");
897
898        synchronized (mSyncRoot) {
899            pw.println("  mOnlyCode=" + mOnlyCore);
900            pw.println("  mSafeMode=" + mSafeMode);
901            pw.println("  mPendingTraversal=" + mPendingTraversal);
902            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
903            pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
904            pw.println("  mDefaultViewport=" + mDefaultViewport);
905            pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
906            pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
907            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
908
909            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
910            ipw.increaseIndent();
911
912            pw.println();
913            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
914            for (DisplayAdapter adapter : mDisplayAdapters) {
915                pw.println("  " + adapter.getName());
916                adapter.dumpLocked(ipw);
917            }
918
919            pw.println();
920            pw.println("Display Devices: size=" + mDisplayDevices.size());
921            for (DisplayDevice device : mDisplayDevices) {
922                pw.println("  " + device.getDisplayDeviceInfoLocked());
923                device.dumpLocked(ipw);
924            }
925
926            final int logicalDisplayCount = mLogicalDisplays.size();
927            pw.println();
928            pw.println("Logical Displays: size=" + logicalDisplayCount);
929            for (int i = 0; i < logicalDisplayCount; i++) {
930                int displayId = mLogicalDisplays.keyAt(i);
931                LogicalDisplay display = mLogicalDisplays.valueAt(i);
932                pw.println("  Display " + displayId + ":");
933                display.dumpLocked(ipw);
934            }
935
936            final int callbackCount = mCallbacks.size();
937            pw.println();
938            pw.println("Callbacks: size=" + callbackCount);
939            for (int i = 0; i < callbackCount; i++) {
940                CallbackRecord callback = mCallbacks.valueAt(i);
941                pw.println("  " + i + ": mPid=" + callback.mPid
942                        + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
943            }
944
945            if (mDisplayPowerController != null) {
946                mDisplayPowerController.dump(pw);
947            }
948        }
949    }
950
951    /**
952     * This is the object that everything in the display manager locks on.
953     * We make it an inner class within the {@link DisplayManagerService} to so that it is
954     * clear that the object belongs to the display manager service and that it is
955     * a unique object with a special purpose.
956     */
957    public static final class SyncRoot {
958    }
959
960    private final class DisplayManagerHandler extends Handler {
961        public DisplayManagerHandler(Looper looper) {
962            super(looper, null, true /*async*/);
963        }
964
965        @Override
966        public void handleMessage(Message msg) {
967            switch (msg.what) {
968                case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
969                    registerDefaultDisplayAdapter();
970                    break;
971
972                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
973                    registerAdditionalDisplayAdapters();
974                    break;
975
976                case MSG_DELIVER_DISPLAY_EVENT:
977                    deliverDisplayEvent(msg.arg1, msg.arg2);
978                    break;
979
980                case MSG_REQUEST_TRAVERSAL:
981                    mWindowManagerInternal.requestTraversalFromDisplayManager();
982                    break;
983
984                case MSG_UPDATE_VIEWPORT: {
985                    synchronized (mSyncRoot) {
986                        mTempDefaultViewport.copyFrom(mDefaultViewport);
987                        mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
988                    }
989                    mInputManagerInternal.setDisplayViewports(
990                            mTempDefaultViewport, mTempExternalTouchViewport);
991                    break;
992                }
993            }
994        }
995    }
996
997    private final class DisplayAdapterListener implements DisplayAdapter.Listener {
998        @Override
999        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1000            switch (event) {
1001                case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1002                    handleDisplayDeviceAdded(device);
1003                    break;
1004
1005                case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1006                    handleDisplayDeviceChanged(device);
1007                    break;
1008
1009                case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1010                    handleDisplayDeviceRemoved(device);
1011                    break;
1012            }
1013        }
1014
1015        @Override
1016        public void onTraversalRequested() {
1017            synchronized (mSyncRoot) {
1018                scheduleTraversalLocked(false);
1019            }
1020        }
1021    }
1022
1023    private final class CallbackRecord implements DeathRecipient {
1024        public final int mPid;
1025        private final IDisplayManagerCallback mCallback;
1026
1027        public boolean mWifiDisplayScanRequested;
1028
1029        public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1030            mPid = pid;
1031            mCallback = callback;
1032        }
1033
1034        @Override
1035        public void binderDied() {
1036            if (DEBUG) {
1037                Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1038            }
1039            onCallbackDied(this);
1040        }
1041
1042        public void notifyDisplayEventAsync(int displayId, int event) {
1043            try {
1044                mCallback.onDisplayEvent(displayId, event);
1045            } catch (RemoteException ex) {
1046                Slog.w(TAG, "Failed to notify process "
1047                        + mPid + " that displays changed, assuming it died.", ex);
1048                binderDied();
1049            }
1050        }
1051    }
1052
1053    private final class BinderService extends IDisplayManager.Stub {
1054        /**
1055         * Returns information about the specified logical display.
1056         *
1057         * @param displayId The logical display id.
1058         * @return The logical display info, or null if the display does not exist.  The
1059         * returned object must be treated as immutable.
1060         */
1061        @Override // Binder call
1062        public DisplayInfo getDisplayInfo(int displayId) {
1063            final int callingUid = Binder.getCallingUid();
1064            final long token = Binder.clearCallingIdentity();
1065            try {
1066                return getDisplayInfoInternal(displayId, callingUid);
1067            } finally {
1068                Binder.restoreCallingIdentity(token);
1069            }
1070        }
1071
1072        /**
1073         * Returns the list of all display ids.
1074         */
1075        @Override // Binder call
1076        public int[] getDisplayIds() {
1077            final int callingUid = Binder.getCallingUid();
1078            final long token = Binder.clearCallingIdentity();
1079            try {
1080                return getDisplayIdsInternal(callingUid);
1081            } finally {
1082                Binder.restoreCallingIdentity(token);
1083            }
1084        }
1085
1086        @Override // Binder call
1087        public void registerCallback(IDisplayManagerCallback callback) {
1088            if (callback == null) {
1089                throw new IllegalArgumentException("listener must not be null");
1090            }
1091
1092            final int callingPid = Binder.getCallingPid();
1093            final long token = Binder.clearCallingIdentity();
1094            try {
1095                registerCallbackInternal(callback, callingPid);
1096            } finally {
1097                Binder.restoreCallingIdentity(token);
1098            }
1099        }
1100
1101        @Override // Binder call
1102        public void startWifiDisplayScan() {
1103            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1104                    "Permission required to start wifi display scans");
1105
1106            final int callingPid = Binder.getCallingPid();
1107            final long token = Binder.clearCallingIdentity();
1108            try {
1109                startWifiDisplayScanInternal(callingPid);
1110            } finally {
1111                Binder.restoreCallingIdentity(token);
1112            }
1113        }
1114
1115        @Override // Binder call
1116        public void stopWifiDisplayScan() {
1117            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1118                    "Permission required to stop wifi display scans");
1119
1120            final int callingPid = Binder.getCallingPid();
1121            final long token = Binder.clearCallingIdentity();
1122            try {
1123                stopWifiDisplayScanInternal(callingPid);
1124            } finally {
1125                Binder.restoreCallingIdentity(token);
1126            }
1127        }
1128
1129        @Override // Binder call
1130        public void connectWifiDisplay(String address) {
1131            if (address == null) {
1132                throw new IllegalArgumentException("address must not be null");
1133            }
1134            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1135                    "Permission required to connect to a wifi display");
1136
1137            final long token = Binder.clearCallingIdentity();
1138            try {
1139                connectWifiDisplayInternal(address);
1140            } finally {
1141                Binder.restoreCallingIdentity(token);
1142            }
1143        }
1144
1145        @Override // Binder call
1146        public void disconnectWifiDisplay() {
1147            // This request does not require special permissions.
1148            // Any app can request disconnection from the currently active wifi display.
1149            // This exception should no longer be needed once wifi display control moves
1150            // to the media router service.
1151
1152            final long token = Binder.clearCallingIdentity();
1153            try {
1154                disconnectWifiDisplayInternal();
1155            } finally {
1156                Binder.restoreCallingIdentity(token);
1157            }
1158        }
1159
1160        @Override // Binder call
1161        public void renameWifiDisplay(String address, String alias) {
1162            if (address == null) {
1163                throw new IllegalArgumentException("address must not be null");
1164            }
1165            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1166                    "Permission required to rename to a wifi display");
1167
1168            final long token = Binder.clearCallingIdentity();
1169            try {
1170                renameWifiDisplayInternal(address, alias);
1171            } finally {
1172                Binder.restoreCallingIdentity(token);
1173            }
1174        }
1175
1176        @Override // Binder call
1177        public void forgetWifiDisplay(String address) {
1178            if (address == null) {
1179                throw new IllegalArgumentException("address must not be null");
1180            }
1181            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1182                    "Permission required to forget to a wifi display");
1183
1184            final long token = Binder.clearCallingIdentity();
1185            try {
1186                forgetWifiDisplayInternal(address);
1187            } finally {
1188                Binder.restoreCallingIdentity(token);
1189            }
1190        }
1191
1192        @Override // Binder call
1193        public void pauseWifiDisplay() {
1194            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1195                    "Permission required to pause a wifi display session");
1196
1197            final long token = Binder.clearCallingIdentity();
1198            try {
1199                pauseWifiDisplayInternal();
1200            } finally {
1201                Binder.restoreCallingIdentity(token);
1202            }
1203        }
1204
1205        @Override // Binder call
1206        public void resumeWifiDisplay() {
1207            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1208                    "Permission required to resume a wifi display session");
1209
1210            final long token = Binder.clearCallingIdentity();
1211            try {
1212                resumeWifiDisplayInternal();
1213            } finally {
1214                Binder.restoreCallingIdentity(token);
1215            }
1216        }
1217
1218        @Override // Binder call
1219        public WifiDisplayStatus getWifiDisplayStatus() {
1220            // This request does not require special permissions.
1221            // Any app can get information about available wifi displays.
1222
1223            final long token = Binder.clearCallingIdentity();
1224            try {
1225                return getWifiDisplayStatusInternal();
1226            } finally {
1227                Binder.restoreCallingIdentity(token);
1228            }
1229        }
1230
1231        @Override // Binder call
1232        public int createVirtualDisplay(IVirtualDisplayCallbacks callbacks,
1233                IMediaProjection projection, String packageName, String name,
1234                int width, int height, int densityDpi, Surface surface, int flags) {
1235            final int callingUid = Binder.getCallingUid();
1236            if (!validatePackageName(callingUid, packageName)) {
1237                throw new SecurityException("packageName must match the calling uid");
1238            }
1239            if (callbacks == null) {
1240                throw new IllegalArgumentException("appToken must not be null");
1241            }
1242            if (TextUtils.isEmpty(name)) {
1243                throw new IllegalArgumentException("name must be non-null and non-empty");
1244            }
1245            if (width <= 0 || height <= 0 || densityDpi <= 0) {
1246                throw new IllegalArgumentException("width, height, and densityDpi must be "
1247                        + "greater than 0");
1248            }
1249
1250            if (projection != null) {
1251                try {
1252                    if (!getProjectionService().isValidMediaProjection(projection)) {
1253                        throw new SecurityException("Invalid media projection");
1254                    }
1255                } catch (RemoteException e) {
1256                    throw new SecurityException("unable to validate media projection");
1257                }
1258                flags &= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
1259                try {
1260                    flags |= projection.getVirtualDisplayFlags();
1261                } catch (RemoteException e) {
1262                    throw new RuntimeException("unable to retrieve media projection flags");
1263                }
1264            }
1265
1266            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SCREEN_SHARE) != 0) {
1267                if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0 ||
1268                        (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
1269                    throw new IllegalArgumentException("screen sharing virtual displays must not "
1270                            + "be public or presentation displays");
1271                }
1272                if (!canProjectVideo(projection)) {
1273                    throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1274                            + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1275                            + "MediaProjection token in order to create a screen sharing virtual "
1276                            + "display.");
1277                }
1278            }
1279
1280
1281            if (callingUid != Process.SYSTEM_UID &&
1282                    (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1283                if (!canProjectVideo(projection)) {
1284                    throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1285                            + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1286                            + "MediaProjection token to create a public virtual display.");
1287                }
1288            }
1289            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1290                if (!canProjectSecureVideo(projection)) {
1291                    throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1292                            + "or an appropriate MediaProjection token to create a "
1293                            + "secure virtual display.");
1294                }
1295            }
1296
1297            final long token = Binder.clearCallingIdentity();
1298            try {
1299                return createVirtualDisplayInternal(callbacks, projection, callingUid,
1300                        packageName, name, width, height, densityDpi, surface, flags);
1301            } finally {
1302                Binder.restoreCallingIdentity(token);
1303            }
1304        }
1305
1306        @Override // Binder call
1307        public void setVirtualDisplaySurface(IVirtualDisplayCallbacks callbacks, Surface surface) {
1308            final long token = Binder.clearCallingIdentity();
1309            try {
1310                setVirtualDisplaySurfaceInternal(callbacks.asBinder(), surface);
1311            } finally {
1312                Binder.restoreCallingIdentity(token);
1313            }
1314        }
1315
1316        @Override // Binder call
1317        public void releaseVirtualDisplay(IVirtualDisplayCallbacks callbacks) {
1318            final long token = Binder.clearCallingIdentity();
1319            try {
1320                releaseVirtualDisplayInternal(callbacks.asBinder());
1321            } finally {
1322                Binder.restoreCallingIdentity(token);
1323            }
1324        }
1325
1326        @Override // Binder call
1327        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1328            if (mContext == null
1329                    || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1330                            != PackageManager.PERMISSION_GRANTED) {
1331                pw.println("Permission Denial: can't dump DisplayManager from from pid="
1332                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1333                return;
1334            }
1335
1336            final long token = Binder.clearCallingIdentity();
1337            try {
1338                dumpInternal(pw);
1339            } finally {
1340                Binder.restoreCallingIdentity(token);
1341            }
1342        }
1343
1344        private boolean validatePackageName(int uid, String packageName) {
1345            if (packageName != null) {
1346                String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1347                if (packageNames != null) {
1348                    for (String n : packageNames) {
1349                        if (n.equals(packageName)) {
1350                            return true;
1351                        }
1352                    }
1353                }
1354            }
1355            return false;
1356        }
1357
1358        private boolean canProjectVideo(IMediaProjection projection) {
1359            if (projection != null) {
1360                try {
1361                    if (projection.canProjectVideo()) {
1362                        return true;
1363                    }
1364                } catch (RemoteException e) {
1365                    Slog.e(TAG, "Unable to query projection service for permissions", e);
1366                }
1367            }
1368            if (mContext.checkCallingPermission(
1369                    android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1370                    != PackageManager.PERMISSION_GRANTED) {
1371                return true;
1372            }
1373            return canProjectSecureVideo(projection);
1374        }
1375
1376        private boolean canProjectSecureVideo(IMediaProjection projection) {
1377            if (projection != null) {
1378                try {
1379                    if (projection.canProjectSecureVideo()){
1380                        return true;
1381                    }
1382                } catch (RemoteException e) {
1383                    Slog.e(TAG, "Unable to query projection service for permissions", e);
1384                }
1385            }
1386            return mContext.checkCallingPermission(
1387                    android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1388                    != PackageManager.PERMISSION_GRANTED;
1389        }
1390    }
1391
1392    private final class LocalService extends DisplayManagerInternal {
1393        @Override
1394        public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
1395                SensorManager sensorManager) {
1396            synchronized (mSyncRoot) {
1397                DisplayBlanker blanker = new DisplayBlanker() {
1398                    @Override
1399                    public void requestDisplayState(int state) {
1400                        // The order of operations is important for legacy reasons.
1401                        if (state == Display.STATE_OFF) {
1402                            requestGlobalDisplayStateInternal(state);
1403                        }
1404
1405                        callbacks.onDisplayStateChange(state);
1406
1407                        if (state != Display.STATE_OFF) {
1408                            requestGlobalDisplayStateInternal(state);
1409                        }
1410                    }
1411                };
1412                mDisplayPowerController = new DisplayPowerController(
1413                        mContext, callbacks, handler, sensorManager, blanker);
1414            }
1415        }
1416
1417        @Override
1418        public boolean requestPowerState(DisplayPowerRequest request,
1419                boolean waitForNegativeProximity) {
1420            return mDisplayPowerController.requestPowerState(request,
1421                    waitForNegativeProximity);
1422        }
1423
1424        @Override
1425        public boolean isProximitySensorAvailable() {
1426            return mDisplayPowerController.isProximitySensorAvailable();
1427        }
1428
1429        @Override
1430        public DisplayInfo getDisplayInfo(int displayId) {
1431            return getDisplayInfoInternal(displayId, Process.myUid());
1432        }
1433
1434        @Override
1435        public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1436            if (listener == null) {
1437                throw new IllegalArgumentException("listener must not be null");
1438            }
1439
1440            registerDisplayTransactionListenerInternal(listener);
1441        }
1442
1443        @Override
1444        public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1445            if (listener == null) {
1446                throw new IllegalArgumentException("listener must not be null");
1447            }
1448
1449            unregisterDisplayTransactionListenerInternal(listener);
1450        }
1451
1452        @Override
1453        public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1454            setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1455        }
1456
1457        @Override
1458        public void performTraversalInTransactionFromWindowManager() {
1459            performTraversalInTransactionFromWindowManagerInternal();
1460        }
1461
1462        @Override
1463        public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
1464            setDisplayHasContentInternal(displayId, hasContent, inTraversal);
1465        }
1466    }
1467}
1468