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