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