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