DisplayManagerService.java revision 01e840ff9441e005153d799e71d65b38bcb21902
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 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 setDisplayHasContentInternal(int displayId, boolean hasContent,
781            boolean inTraversal) {
782        synchronized (mSyncRoot) {
783            LogicalDisplay display = mLogicalDisplays.get(displayId);
784            if (display != null && display.hasContentLocked() != hasContent) {
785                if (DEBUG) {
786                    Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
787                            + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
788                }
789
790                display.setHasContentLocked(hasContent);
791                scheduleTraversalLocked(inTraversal);
792            }
793        }
794    }
795
796    private void clearViewportsLocked() {
797        mDefaultViewport.valid = false;
798        mExternalTouchViewport.valid = false;
799    }
800
801    private void configureDisplayInTransactionLocked(DisplayDevice device) {
802        final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
803        final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
804
805        // Find the logical display that the display device is showing.
806        // Certain displays only ever show their own content.
807        LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
808        if (!ownContent) {
809            if (display != null && !display.hasContentLocked()) {
810                // If the display does not have any content of its own, then
811                // automatically mirror the default logical display contents.
812                display = null;
813            }
814            if (display == null) {
815                display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
816            }
817        }
818
819        // Apply the logical display configuration to the display device.
820        if (display == null) {
821            // TODO: no logical display for the device, blank it
822            Slog.w(TAG, "Missing logical display to use for physical display device: "
823                    + device.getDisplayDeviceInfoLocked());
824            return;
825        }
826        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
827
828        // Update the viewports if needed.
829        if (!mDefaultViewport.valid
830                && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
831            setViewportLocked(mDefaultViewport, display, device);
832        }
833        if (!mExternalTouchViewport.valid
834                && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
835            setViewportLocked(mExternalTouchViewport, display, device);
836        }
837    }
838
839    private static void setViewportLocked(DisplayViewport viewport,
840            LogicalDisplay display, DisplayDevice device) {
841        viewport.valid = true;
842        viewport.displayId = display.getDisplayIdLocked();
843        device.populateViewportLocked(viewport);
844    }
845
846    private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
847        final int count = mLogicalDisplays.size();
848        for (int i = 0; i < count; i++) {
849            LogicalDisplay display = mLogicalDisplays.valueAt(i);
850            if (display.getPrimaryDisplayDeviceLocked() == device) {
851                return display;
852            }
853        }
854        return null;
855    }
856
857    private void sendDisplayEventLocked(int displayId, int event) {
858        Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
859        mHandler.sendMessage(msg);
860    }
861
862    // Requests that performTraversalsInTransactionFromWindowManager be called at a
863    // later time to apply changes to surfaces and displays.
864    private void scheduleTraversalLocked(boolean inTraversal) {
865        if (!mPendingTraversal && mWindowManagerInternal != null) {
866            mPendingTraversal = true;
867            if (!inTraversal) {
868                mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
869            }
870        }
871    }
872
873    // Runs on Handler thread.
874    // Delivers display event notifications to callbacks.
875    private void deliverDisplayEvent(int displayId, int event) {
876        if (DEBUG) {
877            Slog.d(TAG, "Delivering display event: displayId="
878                    + displayId + ", event=" + event);
879        }
880
881        // Grab the lock and copy the callbacks.
882        final int count;
883        synchronized (mSyncRoot) {
884            count = mCallbacks.size();
885            mTempCallbacks.clear();
886            for (int i = 0; i < count; i++) {
887                mTempCallbacks.add(mCallbacks.valueAt(i));
888            }
889        }
890
891        // After releasing the lock, send the notifications out.
892        for (int i = 0; i < count; i++) {
893            mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
894        }
895        mTempCallbacks.clear();
896    }
897
898    private IMediaProjectionManager getProjectionService() {
899        if (mProjectionService == null) {
900            IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
901            mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
902        }
903        return mProjectionService;
904    }
905
906    private void dumpInternal(PrintWriter pw) {
907        pw.println("DISPLAY MANAGER (dumpsys display)");
908
909        synchronized (mSyncRoot) {
910            pw.println("  mOnlyCode=" + mOnlyCore);
911            pw.println("  mSafeMode=" + mSafeMode);
912            pw.println("  mPendingTraversal=" + mPendingTraversal);
913            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
914            pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
915            pw.println("  mDefaultViewport=" + mDefaultViewport);
916            pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
917            pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
918            pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
919
920            IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
921            ipw.increaseIndent();
922
923            pw.println();
924            pw.println("Display Adapters: size=" + mDisplayAdapters.size());
925            for (DisplayAdapter adapter : mDisplayAdapters) {
926                pw.println("  " + adapter.getName());
927                adapter.dumpLocked(ipw);
928            }
929
930            pw.println();
931            pw.println("Display Devices: size=" + mDisplayDevices.size());
932            for (DisplayDevice device : mDisplayDevices) {
933                pw.println("  " + device.getDisplayDeviceInfoLocked());
934                device.dumpLocked(ipw);
935            }
936
937            final int logicalDisplayCount = mLogicalDisplays.size();
938            pw.println();
939            pw.println("Logical Displays: size=" + logicalDisplayCount);
940            for (int i = 0; i < logicalDisplayCount; i++) {
941                int displayId = mLogicalDisplays.keyAt(i);
942                LogicalDisplay display = mLogicalDisplays.valueAt(i);
943                pw.println("  Display " + displayId + ":");
944                display.dumpLocked(ipw);
945            }
946
947            final int callbackCount = mCallbacks.size();
948            pw.println();
949            pw.println("Callbacks: size=" + callbackCount);
950            for (int i = 0; i < callbackCount; i++) {
951                CallbackRecord callback = mCallbacks.valueAt(i);
952                pw.println("  " + i + ": mPid=" + callback.mPid
953                        + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
954            }
955
956            if (mDisplayPowerController != null) {
957                mDisplayPowerController.dump(pw);
958            }
959        }
960    }
961
962    /**
963     * This is the object that everything in the display manager locks on.
964     * We make it an inner class within the {@link DisplayManagerService} to so that it is
965     * clear that the object belongs to the display manager service and that it is
966     * a unique object with a special purpose.
967     */
968    public static final class SyncRoot {
969    }
970
971    private final class DisplayManagerHandler extends Handler {
972        public DisplayManagerHandler(Looper looper) {
973            super(looper, null, true /*async*/);
974        }
975
976        @Override
977        public void handleMessage(Message msg) {
978            switch (msg.what) {
979                case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
980                    registerDefaultDisplayAdapter();
981                    break;
982
983                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
984                    registerAdditionalDisplayAdapters();
985                    break;
986
987                case MSG_DELIVER_DISPLAY_EVENT:
988                    deliverDisplayEvent(msg.arg1, msg.arg2);
989                    break;
990
991                case MSG_REQUEST_TRAVERSAL:
992                    mWindowManagerInternal.requestTraversalFromDisplayManager();
993                    break;
994
995                case MSG_UPDATE_VIEWPORT: {
996                    synchronized (mSyncRoot) {
997                        mTempDefaultViewport.copyFrom(mDefaultViewport);
998                        mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
999                    }
1000                    mInputManagerInternal.setDisplayViewports(
1001                            mTempDefaultViewport, mTempExternalTouchViewport);
1002                    break;
1003                }
1004            }
1005        }
1006    }
1007
1008    private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1009        @Override
1010        public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1011            switch (event) {
1012                case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1013                    handleDisplayDeviceAdded(device);
1014                    break;
1015
1016                case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1017                    handleDisplayDeviceChanged(device);
1018                    break;
1019
1020                case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1021                    handleDisplayDeviceRemoved(device);
1022                    break;
1023            }
1024        }
1025
1026        @Override
1027        public void onTraversalRequested() {
1028            synchronized (mSyncRoot) {
1029                scheduleTraversalLocked(false);
1030            }
1031        }
1032    }
1033
1034    private final class CallbackRecord implements DeathRecipient {
1035        public final int mPid;
1036        private final IDisplayManagerCallback mCallback;
1037
1038        public boolean mWifiDisplayScanRequested;
1039
1040        public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1041            mPid = pid;
1042            mCallback = callback;
1043        }
1044
1045        @Override
1046        public void binderDied() {
1047            if (DEBUG) {
1048                Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1049            }
1050            onCallbackDied(this);
1051        }
1052
1053        public void notifyDisplayEventAsync(int displayId, int event) {
1054            try {
1055                mCallback.onDisplayEvent(displayId, event);
1056            } catch (RemoteException ex) {
1057                Slog.w(TAG, "Failed to notify process "
1058                        + mPid + " that displays changed, assuming it died.", ex);
1059                binderDied();
1060            }
1061        }
1062    }
1063
1064    private final class BinderService extends IDisplayManager.Stub {
1065        /**
1066         * Returns information about the specified logical display.
1067         *
1068         * @param displayId The logical display id.
1069         * @return The logical display info, or null if the display does not exist.  The
1070         * returned object must be treated as immutable.
1071         */
1072        @Override // Binder call
1073        public DisplayInfo getDisplayInfo(int displayId) {
1074            final int callingUid = Binder.getCallingUid();
1075            final long token = Binder.clearCallingIdentity();
1076            try {
1077                return getDisplayInfoInternal(displayId, callingUid);
1078            } finally {
1079                Binder.restoreCallingIdentity(token);
1080            }
1081        }
1082
1083        /**
1084         * Returns the list of all display ids.
1085         */
1086        @Override // Binder call
1087        public int[] getDisplayIds() {
1088            final int callingUid = Binder.getCallingUid();
1089            final long token = Binder.clearCallingIdentity();
1090            try {
1091                return getDisplayIdsInternal(callingUid);
1092            } finally {
1093                Binder.restoreCallingIdentity(token);
1094            }
1095        }
1096
1097        @Override // Binder call
1098        public void registerCallback(IDisplayManagerCallback callback) {
1099            if (callback == null) {
1100                throw new IllegalArgumentException("listener must not be null");
1101            }
1102
1103            final int callingPid = Binder.getCallingPid();
1104            final long token = Binder.clearCallingIdentity();
1105            try {
1106                registerCallbackInternal(callback, callingPid);
1107            } finally {
1108                Binder.restoreCallingIdentity(token);
1109            }
1110        }
1111
1112        @Override // Binder call
1113        public void startWifiDisplayScan() {
1114            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1115                    "Permission required to start wifi display scans");
1116
1117            final int callingPid = Binder.getCallingPid();
1118            final long token = Binder.clearCallingIdentity();
1119            try {
1120                startWifiDisplayScanInternal(callingPid);
1121            } finally {
1122                Binder.restoreCallingIdentity(token);
1123            }
1124        }
1125
1126        @Override // Binder call
1127        public void stopWifiDisplayScan() {
1128            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1129                    "Permission required to stop wifi display scans");
1130
1131            final int callingPid = Binder.getCallingPid();
1132            final long token = Binder.clearCallingIdentity();
1133            try {
1134                stopWifiDisplayScanInternal(callingPid);
1135            } finally {
1136                Binder.restoreCallingIdentity(token);
1137            }
1138        }
1139
1140        @Override // Binder call
1141        public void connectWifiDisplay(String address) {
1142            if (address == null) {
1143                throw new IllegalArgumentException("address must not be null");
1144            }
1145            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1146                    "Permission required to connect to a wifi display");
1147
1148            final long token = Binder.clearCallingIdentity();
1149            try {
1150                connectWifiDisplayInternal(address);
1151            } finally {
1152                Binder.restoreCallingIdentity(token);
1153            }
1154        }
1155
1156        @Override // Binder call
1157        public void disconnectWifiDisplay() {
1158            // This request does not require special permissions.
1159            // Any app can request disconnection from the currently active wifi display.
1160            // This exception should no longer be needed once wifi display control moves
1161            // to the media router service.
1162
1163            final long token = Binder.clearCallingIdentity();
1164            try {
1165                disconnectWifiDisplayInternal();
1166            } finally {
1167                Binder.restoreCallingIdentity(token);
1168            }
1169        }
1170
1171        @Override // Binder call
1172        public void renameWifiDisplay(String address, String alias) {
1173            if (address == null) {
1174                throw new IllegalArgumentException("address must not be null");
1175            }
1176            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1177                    "Permission required to rename to a wifi display");
1178
1179            final long token = Binder.clearCallingIdentity();
1180            try {
1181                renameWifiDisplayInternal(address, alias);
1182            } finally {
1183                Binder.restoreCallingIdentity(token);
1184            }
1185        }
1186
1187        @Override // Binder call
1188        public void forgetWifiDisplay(String address) {
1189            if (address == null) {
1190                throw new IllegalArgumentException("address must not be null");
1191            }
1192            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1193                    "Permission required to forget to a wifi display");
1194
1195            final long token = Binder.clearCallingIdentity();
1196            try {
1197                forgetWifiDisplayInternal(address);
1198            } finally {
1199                Binder.restoreCallingIdentity(token);
1200            }
1201        }
1202
1203        @Override // Binder call
1204        public void pauseWifiDisplay() {
1205            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1206                    "Permission required to pause a wifi display session");
1207
1208            final long token = Binder.clearCallingIdentity();
1209            try {
1210                pauseWifiDisplayInternal();
1211            } finally {
1212                Binder.restoreCallingIdentity(token);
1213            }
1214        }
1215
1216        @Override // Binder call
1217        public void resumeWifiDisplay() {
1218            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1219                    "Permission required to resume a wifi display session");
1220
1221            final long token = Binder.clearCallingIdentity();
1222            try {
1223                resumeWifiDisplayInternal();
1224            } finally {
1225                Binder.restoreCallingIdentity(token);
1226            }
1227        }
1228
1229        @Override // Binder call
1230        public WifiDisplayStatus getWifiDisplayStatus() {
1231            // This request does not require special permissions.
1232            // Any app can get information about available wifi displays.
1233
1234            final long token = Binder.clearCallingIdentity();
1235            try {
1236                return getWifiDisplayStatusInternal();
1237            } finally {
1238                Binder.restoreCallingIdentity(token);
1239            }
1240        }
1241
1242        @Override // Binder call
1243        public int createVirtualDisplay(IVirtualDisplayCallbacks callbacks,
1244                IMediaProjection projection, String packageName, String name,
1245                int width, int height, int densityDpi, Surface surface, int flags) {
1246            final int callingUid = Binder.getCallingUid();
1247            if (!validatePackageName(callingUid, packageName)) {
1248                throw new SecurityException("packageName must match the calling uid");
1249            }
1250            if (callbacks == null) {
1251                throw new IllegalArgumentException("appToken must not be null");
1252            }
1253            if (TextUtils.isEmpty(name)) {
1254                throw new IllegalArgumentException("name must be non-null and non-empty");
1255            }
1256            if (width <= 0 || height <= 0 || densityDpi <= 0) {
1257                throw new IllegalArgumentException("width, height, and densityDpi must be "
1258                        + "greater than 0");
1259            }
1260
1261            if (projection != null) {
1262                try {
1263                    if (!getProjectionService().isValidMediaProjection(projection)) {
1264                        throw new SecurityException("Invalid media projection");
1265                    }
1266                } catch (RemoteException e) {
1267                    throw new SecurityException("unable to validate media projection");
1268                }
1269                flags &= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
1270                try {
1271                    flags |= projection.getVirtualDisplayFlags();
1272                } catch (RemoteException e) {
1273                    throw new RuntimeException("unable to retrieve media projection flags");
1274                }
1275            }
1276
1277            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SCREEN_SHARE) != 0) {
1278                if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0 ||
1279                        (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
1280                    throw new IllegalArgumentException("screen sharing virtual displays must not "
1281                            + "be public or presentation displays");
1282                }
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 in order to create a screen sharing virtual "
1287                            + "display.");
1288                }
1289            }
1290
1291
1292            if (callingUid != Process.SYSTEM_UID &&
1293                    (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1294                if (!canProjectVideo(projection)) {
1295                    throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1296                            + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
1297                            + "MediaProjection token to create a public virtual display.");
1298                }
1299            }
1300            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1301                if (!canProjectSecureVideo(projection)) {
1302                    throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1303                            + "or an appropriate MediaProjection token to create a "
1304                            + "secure virtual display.");
1305                }
1306            }
1307
1308            final long token = Binder.clearCallingIdentity();
1309            try {
1310                return createVirtualDisplayInternal(callbacks, projection, callingUid,
1311                        packageName, name, width, height, densityDpi, surface, flags);
1312            } finally {
1313                Binder.restoreCallingIdentity(token);
1314            }
1315        }
1316
1317        @Override // Binder call
1318        public void resizeVirtualDisplay(IVirtualDisplayCallbacks callbacks,
1319                int width, int height, int densityDpi) {
1320            final long token = Binder.clearCallingIdentity();
1321            try {
1322                resizeVirtualDisplayInternal(callbacks.asBinder(), width, height, densityDpi);
1323            } finally {
1324                Binder.restoreCallingIdentity(token);
1325            }
1326        }
1327
1328        @Override // Binder call
1329        public void setVirtualDisplaySurface(IVirtualDisplayCallbacks callbacks, Surface surface) {
1330            final long token = Binder.clearCallingIdentity();
1331            try {
1332                setVirtualDisplaySurfaceInternal(callbacks.asBinder(), surface);
1333            } finally {
1334                Binder.restoreCallingIdentity(token);
1335            }
1336        }
1337
1338        @Override // Binder call
1339        public void releaseVirtualDisplay(IVirtualDisplayCallbacks callbacks) {
1340            final long token = Binder.clearCallingIdentity();
1341            try {
1342                releaseVirtualDisplayInternal(callbacks.asBinder());
1343            } finally {
1344                Binder.restoreCallingIdentity(token);
1345            }
1346        }
1347
1348        @Override // Binder call
1349        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1350            if (mContext == null
1351                    || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1352                            != PackageManager.PERMISSION_GRANTED) {
1353                pw.println("Permission Denial: can't dump DisplayManager from from pid="
1354                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1355                return;
1356            }
1357
1358            final long token = Binder.clearCallingIdentity();
1359            try {
1360                dumpInternal(pw);
1361            } finally {
1362                Binder.restoreCallingIdentity(token);
1363            }
1364        }
1365
1366        private boolean validatePackageName(int uid, String packageName) {
1367            if (packageName != null) {
1368                String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1369                if (packageNames != null) {
1370                    for (String n : packageNames) {
1371                        if (n.equals(packageName)) {
1372                            return true;
1373                        }
1374                    }
1375                }
1376            }
1377            return false;
1378        }
1379
1380        private boolean canProjectVideo(IMediaProjection projection) {
1381            if (projection != null) {
1382                try {
1383                    if (projection.canProjectVideo()) {
1384                        return true;
1385                    }
1386                } catch (RemoteException e) {
1387                    Slog.e(TAG, "Unable to query projection service for permissions", e);
1388                }
1389            }
1390            if (mContext.checkCallingPermission(
1391                    android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1392                    == PackageManager.PERMISSION_GRANTED) {
1393                return true;
1394            }
1395            return canProjectSecureVideo(projection);
1396        }
1397
1398        private boolean canProjectSecureVideo(IMediaProjection projection) {
1399            if (projection != null) {
1400                try {
1401                    if (projection.canProjectSecureVideo()){
1402                        return true;
1403                    }
1404                } catch (RemoteException e) {
1405                    Slog.e(TAG, "Unable to query projection service for permissions", e);
1406                }
1407            }
1408            return mContext.checkCallingPermission(
1409                    android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1410                    == PackageManager.PERMISSION_GRANTED;
1411        }
1412    }
1413
1414    private final class LocalService extends DisplayManagerInternal {
1415        @Override
1416        public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
1417                SensorManager sensorManager) {
1418            synchronized (mSyncRoot) {
1419                DisplayBlanker blanker = new DisplayBlanker() {
1420                    @Override
1421                    public void requestDisplayState(int state) {
1422                        // The order of operations is important for legacy reasons.
1423                        if (state == Display.STATE_OFF) {
1424                            requestGlobalDisplayStateInternal(state);
1425                        }
1426
1427                        callbacks.onDisplayStateChange(state);
1428
1429                        if (state != Display.STATE_OFF) {
1430                            requestGlobalDisplayStateInternal(state);
1431                        }
1432                    }
1433                };
1434                mDisplayPowerController = new DisplayPowerController(
1435                        mContext, callbacks, handler, sensorManager, blanker);
1436            }
1437        }
1438
1439        @Override
1440        public boolean requestPowerState(DisplayPowerRequest request,
1441                boolean waitForNegativeProximity) {
1442            return mDisplayPowerController.requestPowerState(request,
1443                    waitForNegativeProximity);
1444        }
1445
1446        @Override
1447        public boolean isProximitySensorAvailable() {
1448            return mDisplayPowerController.isProximitySensorAvailable();
1449        }
1450
1451        @Override
1452        public DisplayInfo getDisplayInfo(int displayId) {
1453            return getDisplayInfoInternal(displayId, Process.myUid());
1454        }
1455
1456        @Override
1457        public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1458            if (listener == null) {
1459                throw new IllegalArgumentException("listener must not be null");
1460            }
1461
1462            registerDisplayTransactionListenerInternal(listener);
1463        }
1464
1465        @Override
1466        public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1467            if (listener == null) {
1468                throw new IllegalArgumentException("listener must not be null");
1469            }
1470
1471            unregisterDisplayTransactionListenerInternal(listener);
1472        }
1473
1474        @Override
1475        public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1476            setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1477        }
1478
1479        @Override
1480        public void performTraversalInTransactionFromWindowManager() {
1481            performTraversalInTransactionFromWindowManagerInternal();
1482        }
1483
1484        @Override
1485        public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
1486            setDisplayHasContentInternal(displayId, hasContent, inTraversal);
1487        }
1488    }
1489}
1490