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