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