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.DisplayManagerGlobal;
     25 import android.hardware.display.IDisplayManager;
     26 import android.hardware.display.IDisplayManagerCallback;
     27 import android.hardware.display.WifiDisplayStatus;
     28 import android.os.Binder;
     29 import android.os.Handler;
     30 import android.os.IBinder;
     31 import android.os.Looper;
     32 import android.os.Message;
     33 import android.os.RemoteException;
     34 import android.os.SystemClock;
     35 import android.os.SystemProperties;
     36 import android.util.Slog;
     37 import android.util.SparseArray;
     38 import android.view.Display;
     39 import android.view.DisplayInfo;
     40 
     41 import java.io.FileDescriptor;
     42 import java.io.PrintWriter;
     43 import java.util.ArrayList;
     44 
     45 /**
     46  * Manages attached displays.
     47  * <p>
     48  * The {@link DisplayManagerService} manages the global lifecycle of displays,
     49  * decides how to configure logical displays based on the physical display devices currently
     50  * attached, sends notifications to the system and to applications when the state
     51  * changes, and so on.
     52  * </p><p>
     53  * The display manager service relies on a collection of {@link DisplayAdapter} components,
     54  * for discovering and configuring physical display devices attached to the system.
     55  * There are separate display adapters for each manner that devices are attached:
     56  * one display adapter for built-in local displays, one for simulated non-functional
     57  * displays when the system is headless, one for simulated overlay displays used for
     58  * development, one for wifi displays, etc.
     59  * </p><p>
     60  * Display adapters are only weakly coupled to the display manager service.
     61  * Display adapters communicate changes in display device state to the display manager
     62  * service asynchronously via a {@link DisplayAdapter.Listener} registered
     63  * by the display manager service.  This separation of concerns is important for
     64  * two main reasons.  First, it neatly encapsulates the responsibilities of these
     65  * two classes: display adapters handle individual display devices whereas
     66  * the display manager service handles the global state.  Second, it eliminates
     67  * the potential for deadlocks resulting from asynchronous display device discovery.
     68  * </p>
     69  *
     70  * <h3>Synchronization</h3>
     71  * <p>
     72  * Because the display manager may be accessed by multiple threads, the synchronization
     73  * story gets a little complicated.  In particular, the window manager may call into
     74  * the display manager while holding a surface transaction with the expectation that
     75  * it can apply changes immediately.  Unfortunately, that means we can't just do
     76  * everything asynchronously (*grump*).
     77  * </p><p>
     78  * To make this work, all of the objects that belong to the display manager must
     79  * use the same lock.  We call this lock the synchronization root and it has a unique
     80  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
     81  * named with the "Locked" suffix.
     82  * </p><p>
     83  * Where things get tricky is that the display manager is not allowed to make
     84  * any potentially reentrant calls, especially into the window manager.  We generally
     85  * avoid this by making all potentially reentrant out-calls asynchronous.
     86  * </p>
     87  */
     88 public final class DisplayManagerService extends IDisplayManager.Stub {
     89     private static final String TAG = "DisplayManagerService";
     90     private static final boolean DEBUG = false;
     91 
     92     // When this system property is set to 0, WFD is forcibly disabled on boot.
     93     // When this system property is set to 1, WFD is forcibly enabled on boot.
     94     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
     95     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
     96 
     97     private static final String SYSTEM_HEADLESS = "ro.config.headless";
     98     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
     99 
    100     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
    101     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
    102     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
    103     private static final int MSG_REQUEST_TRAVERSAL = 4;
    104     private static final int MSG_UPDATE_VIEWPORT = 5;
    105 
    106     private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
    107     private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
    108     private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
    109 
    110     private final Context mContext;
    111     private final boolean mHeadless;
    112     private final DisplayManagerHandler mHandler;
    113     private final Handler mUiHandler;
    114     private final DisplayAdapterListener mDisplayAdapterListener;
    115     private WindowManagerFuncs mWindowManagerFuncs;
    116     private InputManagerFuncs mInputManagerFuncs;
    117 
    118     // The synchronization root for the display manager.
    119     // This lock guards most of the display manager's state.
    120     private final SyncRoot mSyncRoot = new SyncRoot();
    121 
    122     // True if in safe mode.
    123     // This option may disable certain display adapters.
    124     public boolean mSafeMode;
    125 
    126     // True if we are in a special boot mode where only core applications and
    127     // services should be started.  This option may disable certain display adapters.
    128     public boolean mOnlyCore;
    129 
    130     // True if the display manager service should pretend there is only one display
    131     // and only tell applications about the existence of the default logical display.
    132     // The display manager can still mirror content to secondary displays but applications
    133     // cannot present unique content on those displays.
    134     // Used for demonstration purposes only.
    135     private final boolean mSingleDisplayDemoMode;
    136 
    137     // All callback records indexed by calling process id.
    138     public final SparseArray<CallbackRecord> mCallbacks =
    139             new SparseArray<CallbackRecord>();
    140 
    141     // List of all currently registered display adapters.
    142     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
    143 
    144     // List of all currently connected display devices.
    145     private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
    146 
    147     // List of all removed display devices.
    148     private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
    149 
    150     // List of all logical displays indexed by logical display id.
    151     private final SparseArray<LogicalDisplay> mLogicalDisplays =
    152             new SparseArray<LogicalDisplay>();
    153     private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
    154 
    155     // Set to true if all displays have been blanked by the power manager.
    156     private int mAllDisplayBlankStateFromPowerManager;
    157 
    158     // Set to true when there are pending display changes that have yet to be applied
    159     // to the surface flinger state.
    160     private boolean mPendingTraversal;
    161 
    162     // The Wifi display adapter, or null if not registered.
    163     private WifiDisplayAdapter mWifiDisplayAdapter;
    164 
    165     // Viewports of the default display and the display that should receive touch
    166     // input from an external source.  Used by the input system.
    167     private final DisplayViewport mDefaultViewport = new DisplayViewport();
    168     private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
    169 
    170     // Persistent data store for all internal settings maintained by the display manager service.
    171     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
    172 
    173     // Temporary callback list, used when sending display events to applications.
    174     // May be used outside of the lock but only on the handler thread.
    175     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
    176 
    177     // Temporary display info, used for comparing display configurations.
    178     private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
    179 
    180     // Temporary viewports, used when sending new viewport information to the
    181     // input system.  May be used outside of the lock but only on the handler thread.
    182     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
    183     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
    184 
    185     public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
    186         mContext = context;
    187         mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
    188 
    189         mHandler = new DisplayManagerHandler(mainHandler.getLooper());
    190         mUiHandler = uiHandler;
    191         mDisplayAdapterListener = new DisplayAdapterListener();
    192         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
    193 
    194         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
    195     }
    196 
    197     /**
    198      * Pauses the boot process to wait for the first display to be initialized.
    199      */
    200     public boolean waitForDefaultDisplay() {
    201         synchronized (mSyncRoot) {
    202             long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
    203             while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
    204                 long delay = timeout - SystemClock.uptimeMillis();
    205                 if (delay <= 0) {
    206                     return false;
    207                 }
    208                 if (DEBUG) {
    209                     Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
    210                 }
    211                 try {
    212                     mSyncRoot.wait(delay);
    213                 } catch (InterruptedException ex) {
    214                 }
    215             }
    216         }
    217         return true;
    218     }
    219 
    220     /**
    221      * Called during initialization to associate the display manager with the
    222      * window manager.
    223      */
    224     public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
    225         synchronized (mSyncRoot) {
    226             mWindowManagerFuncs = windowManagerFuncs;
    227             scheduleTraversalLocked(false);
    228         }
    229     }
    230 
    231     /**
    232      * Called during initialization to associate the display manager with the
    233      * input manager.
    234      */
    235     public void setInputManager(InputManagerFuncs inputManagerFuncs) {
    236         synchronized (mSyncRoot) {
    237             mInputManagerFuncs = inputManagerFuncs;
    238             scheduleTraversalLocked(false);
    239         }
    240     }
    241 
    242     /**
    243      * Called when the system is ready to go.
    244      */
    245     public void systemReady(boolean safeMode, boolean onlyCore) {
    246         synchronized (mSyncRoot) {
    247             mSafeMode = safeMode;
    248             mOnlyCore = onlyCore;
    249         }
    250 
    251         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
    252     }
    253 
    254     /**
    255      * Returns true if the device is headless.
    256      *
    257      * @return True if the device is headless.
    258      */
    259     public boolean isHeadless() {
    260         return mHeadless;
    261     }
    262 
    263     /**
    264      * Overrides the display information of a particular logical display.
    265      * This is used by the window manager to control the size and characteristics
    266      * of the default display.  It is expected to apply the requested change
    267      * to the display information synchronously so that applications will immediately
    268      * observe the new state.
    269      *
    270      * @param displayId The logical display id.
    271      * @param info The new data to be stored.
    272      */
    273     public void setDisplayInfoOverrideFromWindowManager(
    274             int displayId, DisplayInfo info) {
    275         synchronized (mSyncRoot) {
    276             LogicalDisplay display = mLogicalDisplays.get(displayId);
    277             if (display != null) {
    278                 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
    279                 display.setDisplayInfoOverrideFromWindowManagerLocked(info);
    280                 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
    281                     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
    282                     scheduleTraversalLocked(false);
    283                 }
    284             }
    285         }
    286     }
    287 
    288     /**
    289      * Called by the window manager to perform traversals while holding a
    290      * surface flinger transaction.
    291      */
    292     public void performTraversalInTransactionFromWindowManager() {
    293         synchronized (mSyncRoot) {
    294             if (!mPendingTraversal) {
    295                 return;
    296             }
    297             mPendingTraversal = false;
    298 
    299             performTraversalInTransactionLocked();
    300         }
    301     }
    302 
    303     /**
    304      * Called by the power manager to blank all displays.
    305      */
    306     public void blankAllDisplaysFromPowerManager() {
    307         synchronized (mSyncRoot) {
    308             if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
    309                 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
    310 
    311                 final int count = mDisplayDevices.size();
    312                 for (int i = 0; i < count; i++) {
    313                     DisplayDevice device = mDisplayDevices.get(i);
    314                     device.blankLocked();
    315                 }
    316 
    317                 scheduleTraversalLocked(false);
    318             }
    319         }
    320     }
    321 
    322     /**
    323      * Called by the power manager to unblank all displays.
    324      */
    325     public void unblankAllDisplaysFromPowerManager() {
    326         synchronized (mSyncRoot) {
    327             if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
    328                 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
    329 
    330                 final int count = mDisplayDevices.size();
    331                 for (int i = 0; i < count; i++) {
    332                     DisplayDevice device = mDisplayDevices.get(i);
    333                     device.unblankLocked();
    334                 }
    335 
    336                 scheduleTraversalLocked(false);
    337             }
    338         }
    339     }
    340 
    341     /**
    342      * Returns information about the specified logical display.
    343      *
    344      * @param displayId The logical display id.
    345      * @return The logical display info, or null if the display does not exist.  The
    346      * returned object must be treated as immutable.
    347      */
    348     @Override // Binder call
    349     public DisplayInfo getDisplayInfo(int displayId) {
    350         synchronized (mSyncRoot) {
    351             LogicalDisplay display = mLogicalDisplays.get(displayId);
    352             if (display != null) {
    353                 return display.getDisplayInfoLocked();
    354             }
    355             return null;
    356         }
    357     }
    358 
    359     /**
    360      * Returns the list of all display ids.
    361      */
    362     @Override // Binder call
    363     public int[] getDisplayIds() {
    364         synchronized (mSyncRoot) {
    365             final int count = mLogicalDisplays.size();
    366             int[] displayIds = new int[count];
    367             for (int i = 0; i < count; i++) {
    368                 displayIds[i] = mLogicalDisplays.keyAt(i);
    369             }
    370             return displayIds;
    371         }
    372     }
    373 
    374     @Override // Binder call
    375     public void registerCallback(IDisplayManagerCallback callback) {
    376         if (callback == null) {
    377             throw new IllegalArgumentException("listener must not be null");
    378         }
    379 
    380         synchronized (mSyncRoot) {
    381             int callingPid = Binder.getCallingPid();
    382             if (mCallbacks.get(callingPid) != null) {
    383                 throw new SecurityException("The calling process has already "
    384                         + "registered an IDisplayManagerCallback.");
    385             }
    386 
    387             CallbackRecord record = new CallbackRecord(callingPid, callback);
    388             try {
    389                 IBinder binder = callback.asBinder();
    390                 binder.linkToDeath(record, 0);
    391             } catch (RemoteException ex) {
    392                 // give up
    393                 throw new RuntimeException(ex);
    394             }
    395 
    396             mCallbacks.put(callingPid, record);
    397         }
    398     }
    399 
    400     private void onCallbackDied(int pid) {
    401         synchronized (mSyncRoot) {
    402             mCallbacks.remove(pid);
    403         }
    404     }
    405 
    406     @Override // Binder call
    407     public void scanWifiDisplays() {
    408         final long token = Binder.clearCallingIdentity();
    409         try {
    410             synchronized (mSyncRoot) {
    411                 if (mWifiDisplayAdapter != null) {
    412                     mWifiDisplayAdapter.requestScanLocked();
    413                 }
    414             }
    415         } finally {
    416             Binder.restoreCallingIdentity(token);
    417         }
    418     }
    419 
    420     @Override // Binder call
    421     public void connectWifiDisplay(String address) {
    422         if (address == null) {
    423             throw new IllegalArgumentException("address must not be null");
    424         }
    425 
    426         final boolean trusted = canCallerConfigureWifiDisplay();
    427         final long token = Binder.clearCallingIdentity();
    428         try {
    429             synchronized (mSyncRoot) {
    430                 if (mWifiDisplayAdapter != null) {
    431                     mWifiDisplayAdapter.requestConnectLocked(address, trusted);
    432                 }
    433             }
    434         } finally {
    435             Binder.restoreCallingIdentity(token);
    436         }
    437     }
    438 
    439     @Override // Binder call
    440     public void disconnectWifiDisplay() {
    441         final long token = Binder.clearCallingIdentity();
    442         try {
    443             synchronized (mSyncRoot) {
    444                 if (mWifiDisplayAdapter != null) {
    445                     mWifiDisplayAdapter.requestDisconnectLocked();
    446                 }
    447             }
    448         } finally {
    449             Binder.restoreCallingIdentity(token);
    450         }
    451     }
    452 
    453     @Override // Binder call
    454     public void renameWifiDisplay(String address, String alias) {
    455         if (address == null) {
    456             throw new IllegalArgumentException("address must not be null");
    457         }
    458         if (!canCallerConfigureWifiDisplay()) {
    459             throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
    460                     + "rename a wifi display.");
    461         }
    462 
    463         final long token = Binder.clearCallingIdentity();
    464         try {
    465             synchronized (mSyncRoot) {
    466                 if (mWifiDisplayAdapter != null) {
    467                     mWifiDisplayAdapter.requestRenameLocked(address, alias);
    468                 }
    469             }
    470         } finally {
    471             Binder.restoreCallingIdentity(token);
    472         }
    473     }
    474 
    475     @Override // Binder call
    476     public void forgetWifiDisplay(String address) {
    477         if (address == null) {
    478             throw new IllegalArgumentException("address must not be null");
    479         }
    480         if (!canCallerConfigureWifiDisplay()) {
    481             throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
    482                     + "forget a wifi display.");
    483         }
    484 
    485         final long token = Binder.clearCallingIdentity();
    486         try {
    487             synchronized (mSyncRoot) {
    488                 if (mWifiDisplayAdapter != null) {
    489                     mWifiDisplayAdapter.requestForgetLocked(address);
    490                 }
    491             }
    492         } finally {
    493             Binder.restoreCallingIdentity(token);
    494         }
    495     }
    496 
    497     @Override // Binder call
    498     public WifiDisplayStatus getWifiDisplayStatus() {
    499         final long token = Binder.clearCallingIdentity();
    500         try {
    501             synchronized (mSyncRoot) {
    502                 if (mWifiDisplayAdapter != null) {
    503                     return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
    504                 } else {
    505                     return new WifiDisplayStatus();
    506                 }
    507             }
    508         } finally {
    509             Binder.restoreCallingIdentity(token);
    510         }
    511     }
    512 
    513     private boolean canCallerConfigureWifiDisplay() {
    514         return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
    515                 == PackageManager.PERMISSION_GRANTED;
    516     }
    517 
    518     private void registerDefaultDisplayAdapter() {
    519         // Register default display adapter.
    520         synchronized (mSyncRoot) {
    521             if (mHeadless) {
    522                 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
    523                         mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
    524             } else {
    525                 registerDisplayAdapterLocked(new LocalDisplayAdapter(
    526                         mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
    527             }
    528         }
    529     }
    530 
    531     private void registerAdditionalDisplayAdapters() {
    532         synchronized (mSyncRoot) {
    533             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
    534                 registerOverlayDisplayAdapterLocked();
    535                 registerWifiDisplayAdapterLocked();
    536             }
    537         }
    538     }
    539 
    540     private void registerOverlayDisplayAdapterLocked() {
    541         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
    542                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
    543     }
    544 
    545     private void registerWifiDisplayAdapterLocked() {
    546         if (mContext.getResources().getBoolean(
    547                 com.android.internal.R.bool.config_enableWifiDisplay)
    548                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
    549             mWifiDisplayAdapter = new WifiDisplayAdapter(
    550                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
    551                     mPersistentDataStore);
    552             registerDisplayAdapterLocked(mWifiDisplayAdapter);
    553         }
    554     }
    555 
    556     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
    557         // In safe mode, we disable non-essential display adapters to give the user
    558         // an opportunity to fix broken settings or other problems that might affect
    559         // system stability.
    560         // In only-core mode, we disable non-essential display adapters to minimize
    561         // the number of dependencies that are started while in this mode and to
    562         // prevent problems that might occur due to the device being encrypted.
    563         return !mSafeMode && !mOnlyCore;
    564     }
    565 
    566     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
    567         mDisplayAdapters.add(adapter);
    568         adapter.registerLocked();
    569     }
    570 
    571     private void handleDisplayDeviceAdded(DisplayDevice device) {
    572         synchronized (mSyncRoot) {
    573             if (mDisplayDevices.contains(device)) {
    574                 Slog.w(TAG, "Attempted to add already added display device: "
    575                         + device.getDisplayDeviceInfoLocked());
    576                 return;
    577             }
    578 
    579             Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
    580 
    581             mDisplayDevices.add(device);
    582             addLogicalDisplayLocked(device);
    583             scheduleTraversalLocked(false);
    584 
    585             // Blank or unblank the display immediately to match the state requested
    586             // by the power manager (if known).
    587             switch (mAllDisplayBlankStateFromPowerManager) {
    588                 case DISPLAY_BLANK_STATE_BLANKED:
    589                     device.blankLocked();
    590                     break;
    591                 case DISPLAY_BLANK_STATE_UNBLANKED:
    592                     device.unblankLocked();
    593                     break;
    594             }
    595         }
    596     }
    597 
    598     private void handleDisplayDeviceChanged(DisplayDevice device) {
    599         synchronized (mSyncRoot) {
    600             if (!mDisplayDevices.contains(device)) {
    601                 Slog.w(TAG, "Attempted to change non-existent display device: "
    602                         + device.getDisplayDeviceInfoLocked());
    603                 return;
    604             }
    605 
    606             Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
    607 
    608             device.applyPendingDisplayDeviceInfoChangesLocked();
    609             if (updateLogicalDisplaysLocked()) {
    610                 scheduleTraversalLocked(false);
    611             }
    612         }
    613     }
    614 
    615     private void handleDisplayDeviceRemoved(DisplayDevice device) {
    616         synchronized (mSyncRoot) {
    617             if (!mDisplayDevices.remove(device)) {
    618                 Slog.w(TAG, "Attempted to remove non-existent display device: "
    619                         + device.getDisplayDeviceInfoLocked());
    620                 return;
    621             }
    622 
    623             Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
    624 
    625             mRemovedDisplayDevices.add(device);
    626             updateLogicalDisplaysLocked();
    627             scheduleTraversalLocked(false);
    628         }
    629     }
    630 
    631     // Adds a new logical display based on the given display device.
    632     // Sends notifications if needed.
    633     private void addLogicalDisplayLocked(DisplayDevice device) {
    634         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
    635         boolean isDefault = (deviceInfo.flags
    636                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
    637         if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
    638             Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
    639             isDefault = false;
    640         }
    641 
    642         if (!isDefault && mSingleDisplayDemoMode) {
    643             Slog.i(TAG, "Not creating a logical display for a secondary display "
    644                     + " because single display demo mode is enabled: " + deviceInfo);
    645             return;
    646         }
    647 
    648         final int displayId = assignDisplayIdLocked(isDefault);
    649         final int layerStack = assignLayerStackLocked(displayId);
    650 
    651         LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
    652         display.updateLocked(mDisplayDevices);
    653         if (!display.isValidLocked()) {
    654             // This should never happen currently.
    655             Slog.w(TAG, "Ignoring display device because the logical display "
    656                     + "created from it was not considered valid: " + deviceInfo);
    657             return;
    658         }
    659 
    660         mLogicalDisplays.put(displayId, display);
    661 
    662         // Wake up waitForDefaultDisplay.
    663         if (isDefault) {
    664             mSyncRoot.notifyAll();
    665         }
    666 
    667         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
    668     }
    669 
    670     private int assignDisplayIdLocked(boolean isDefault) {
    671         return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
    672     }
    673 
    674     private int assignLayerStackLocked(int displayId) {
    675         // Currently layer stacks and display ids are the same.
    676         // This need not be the case.
    677         return displayId;
    678     }
    679 
    680     // Updates all existing logical displays given the current set of display devices.
    681     // Removes invalid logical displays.
    682     // Sends notifications if needed.
    683     private boolean updateLogicalDisplaysLocked() {
    684         boolean changed = false;
    685         for (int i = mLogicalDisplays.size(); i-- > 0; ) {
    686             final int displayId = mLogicalDisplays.keyAt(i);
    687             LogicalDisplay display = mLogicalDisplays.valueAt(i);
    688 
    689             mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
    690             display.updateLocked(mDisplayDevices);
    691             if (!display.isValidLocked()) {
    692                 mLogicalDisplays.removeAt(i);
    693                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
    694                 changed = true;
    695             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
    696                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
    697                 changed = true;
    698             }
    699         }
    700         return changed;
    701     }
    702 
    703     private void performTraversalInTransactionLocked() {
    704         // Perform one last traversal for each removed display device.
    705         final int removedCount = mRemovedDisplayDevices.size();
    706         for (int i = 0; i < removedCount; i++) {
    707             DisplayDevice device = mRemovedDisplayDevices.get(i);
    708             device.performTraversalInTransactionLocked();
    709         }
    710         mRemovedDisplayDevices.clear();
    711 
    712         // Clear all viewports before configuring displays so that we can keep
    713         // track of which ones we have configured.
    714         clearViewportsLocked();
    715 
    716         // Configure each display device.
    717         final int count = mDisplayDevices.size();
    718         for (int i = 0; i < count; i++) {
    719             DisplayDevice device = mDisplayDevices.get(i);
    720             configureDisplayInTransactionLocked(device);
    721             device.performTraversalInTransactionLocked();
    722         }
    723 
    724         // Tell the input system about these new viewports.
    725         if (mInputManagerFuncs != null) {
    726             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
    727         }
    728     }
    729 
    730     /**
    731      * Tells the display manager whether there is interesting unique content on the
    732      * specified logical display.  This is used to control automatic mirroring.
    733      * <p>
    734      * If the display has unique content, then the display manager arranges for it
    735      * to be presented on a physical display if appropriate.  Otherwise, the display manager
    736      * may choose to make the physical display mirror some other logical display.
    737      * </p>
    738      *
    739      * @param displayId The logical display id to update.
    740      * @param hasContent True if the logical display has content.
    741      * @param inTraversal True if called from WindowManagerService during a window traversal prior
    742      * to call to performTraversalInTransactionFromWindowManager.
    743      */
    744     public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
    745         synchronized (mSyncRoot) {
    746             LogicalDisplay display = mLogicalDisplays.get(displayId);
    747             if (display != null && display.hasContentLocked() != hasContent) {
    748                 display.setHasContentLocked(hasContent);
    749                 scheduleTraversalLocked(inTraversal);
    750             }
    751         }
    752     }
    753 
    754     private void clearViewportsLocked() {
    755         mDefaultViewport.valid = false;
    756         mExternalTouchViewport.valid = false;
    757     }
    758 
    759     private void configureDisplayInTransactionLocked(DisplayDevice device) {
    760         // Find the logical display that the display device is showing.
    761         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
    762         if (display != null && !display.hasContentLocked()) {
    763             display = null;
    764         }
    765         if (display == null) {
    766             display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
    767         }
    768 
    769         // Apply the logical display configuration to the display device.
    770         if (display == null) {
    771             // TODO: no logical display for the device, blank it
    772             Slog.w(TAG, "Missing logical display to use for physical display device: "
    773                     + device.getDisplayDeviceInfoLocked());
    774             return;
    775         } else {
    776             boolean isBlanked = (mAllDisplayBlankStateFromPowerManager
    777                     == DISPLAY_BLANK_STATE_BLANKED);
    778             display.configureDisplayInTransactionLocked(device, isBlanked);
    779         }
    780 
    781         // Update the viewports if needed.
    782         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    783         if (!mDefaultViewport.valid
    784                 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
    785             setViewportLocked(mDefaultViewport, display, device);
    786         }
    787         if (!mExternalTouchViewport.valid
    788                 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
    789             setViewportLocked(mExternalTouchViewport, display, device);
    790         }
    791     }
    792 
    793     private static void setViewportLocked(DisplayViewport viewport,
    794             LogicalDisplay display, DisplayDevice device) {
    795         viewport.valid = true;
    796         viewport.displayId = display.getDisplayIdLocked();
    797         device.populateViewportLocked(viewport);
    798     }
    799 
    800     private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
    801         final int count = mLogicalDisplays.size();
    802         for (int i = 0; i < count; i++) {
    803             LogicalDisplay display = mLogicalDisplays.valueAt(i);
    804             if (display.getPrimaryDisplayDeviceLocked() == device) {
    805                 return display;
    806             }
    807         }
    808         return null;
    809     }
    810 
    811     private void sendDisplayEventLocked(int displayId, int event) {
    812         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
    813         mHandler.sendMessage(msg);
    814     }
    815 
    816     // Requests that performTraversalsInTransactionFromWindowManager be called at a
    817     // later time to apply changes to surfaces and displays.
    818     private void scheduleTraversalLocked(boolean inTraversal) {
    819         if (!mPendingTraversal && mWindowManagerFuncs != null) {
    820             mPendingTraversal = true;
    821             if (!inTraversal) {
    822                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
    823             }
    824         }
    825     }
    826 
    827     // Runs on Handler thread.
    828     // Delivers display event notifications to callbacks.
    829     private void deliverDisplayEvent(int displayId, int event) {
    830         if (DEBUG) {
    831             Slog.d(TAG, "Delivering display event: displayId="
    832                     + displayId + ", event=" + event);
    833         }
    834 
    835         // Grab the lock and copy the callbacks.
    836         final int count;
    837         synchronized (mSyncRoot) {
    838             count = mCallbacks.size();
    839             mTempCallbacks.clear();
    840             for (int i = 0; i < count; i++) {
    841                 mTempCallbacks.add(mCallbacks.valueAt(i));
    842             }
    843         }
    844 
    845         // After releasing the lock, send the notifications out.
    846         for (int i = 0; i < count; i++) {
    847             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
    848         }
    849         mTempCallbacks.clear();
    850     }
    851 
    852     @Override // Binder call
    853     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
    854         if (mContext == null
    855                 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
    856                         != PackageManager.PERMISSION_GRANTED) {
    857             pw.println("Permission Denial: can't dump DisplayManager from from pid="
    858                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
    859             return;
    860         }
    861 
    862         pw.println("DISPLAY MANAGER (dumpsys display)");
    863 
    864         synchronized (mSyncRoot) {
    865             pw.println("  mHeadless=" + mHeadless);
    866             pw.println("  mOnlyCode=" + mOnlyCore);
    867             pw.println("  mSafeMode=" + mSafeMode);
    868             pw.println("  mPendingTraversal=" + mPendingTraversal);
    869             pw.println("  mAllDisplayBlankStateFromPowerManager="
    870                     + mAllDisplayBlankStateFromPowerManager);
    871             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
    872             pw.println("  mDefaultViewport=" + mDefaultViewport);
    873             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
    874             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
    875 
    876             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
    877             ipw.increaseIndent();
    878 
    879             pw.println();
    880             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
    881             for (DisplayAdapter adapter : mDisplayAdapters) {
    882                 pw.println("  " + adapter.getName());
    883                 adapter.dumpLocked(ipw);
    884             }
    885 
    886             pw.println();
    887             pw.println("Display Devices: size=" + mDisplayDevices.size());
    888             for (DisplayDevice device : mDisplayDevices) {
    889                 pw.println("  " + device.getDisplayDeviceInfoLocked());
    890                 device.dumpLocked(ipw);
    891             }
    892 
    893             final int logicalDisplayCount = mLogicalDisplays.size();
    894             pw.println();
    895             pw.println("Logical Displays: size=" + logicalDisplayCount);
    896             for (int i = 0; i < logicalDisplayCount; i++) {
    897                 int displayId = mLogicalDisplays.keyAt(i);
    898                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
    899                 pw.println("  Display " + displayId + ":");
    900                 display.dumpLocked(ipw);
    901             }
    902         }
    903     }
    904 
    905     /**
    906      * This is the object that everything in the display manager locks on.
    907      * We make it an inner class within the {@link DisplayManagerService} to so that it is
    908      * clear that the object belongs to the display manager service and that it is
    909      * a unique object with a special purpose.
    910      */
    911     public static final class SyncRoot {
    912     }
    913 
    914     /**
    915      * Private interface to the window manager.
    916      */
    917     public interface WindowManagerFuncs {
    918         /**
    919          * Request that the window manager call
    920          * {@link #performTraversalInTransactionFromWindowManager} within a surface
    921          * transaction at a later time.
    922          */
    923         void requestTraversal();
    924     }
    925 
    926     /**
    927      * Private interface to the input manager.
    928      */
    929     public interface InputManagerFuncs {
    930         /**
    931          * Sets information about the displays as needed by the input system.
    932          * The input system should copy this information if required.
    933          */
    934         void setDisplayViewports(DisplayViewport defaultViewport,
    935                 DisplayViewport externalTouchViewport);
    936     }
    937 
    938     private final class DisplayManagerHandler extends Handler {
    939         public DisplayManagerHandler(Looper looper) {
    940             super(looper, null, true /*async*/);
    941         }
    942 
    943         @Override
    944         public void handleMessage(Message msg) {
    945             switch (msg.what) {
    946                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
    947                     registerDefaultDisplayAdapter();
    948                     break;
    949 
    950                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
    951                     registerAdditionalDisplayAdapters();
    952                     break;
    953 
    954                 case MSG_DELIVER_DISPLAY_EVENT:
    955                     deliverDisplayEvent(msg.arg1, msg.arg2);
    956                     break;
    957 
    958                 case MSG_REQUEST_TRAVERSAL:
    959                     mWindowManagerFuncs.requestTraversal();
    960                     break;
    961 
    962                 case MSG_UPDATE_VIEWPORT: {
    963                     synchronized (mSyncRoot) {
    964                         mTempDefaultViewport.copyFrom(mDefaultViewport);
    965                         mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
    966                     }
    967                     mInputManagerFuncs.setDisplayViewports(
    968                             mTempDefaultViewport, mTempExternalTouchViewport);
    969                     break;
    970                 }
    971             }
    972         }
    973     }
    974 
    975     private final class DisplayAdapterListener implements DisplayAdapter.Listener {
    976         @Override
    977         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
    978             switch (event) {
    979                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
    980                     handleDisplayDeviceAdded(device);
    981                     break;
    982 
    983                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
    984                     handleDisplayDeviceChanged(device);
    985                     break;
    986 
    987                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
    988                     handleDisplayDeviceRemoved(device);
    989                     break;
    990             }
    991         }
    992 
    993         @Override
    994         public void onTraversalRequested() {
    995             synchronized (mSyncRoot) {
    996                 scheduleTraversalLocked(false);
    997             }
    998         }
    999     }
   1000 
   1001     private final class CallbackRecord implements DeathRecipient {
   1002         private final int mPid;
   1003         private final IDisplayManagerCallback mCallback;
   1004 
   1005         public CallbackRecord(int pid, IDisplayManagerCallback callback) {
   1006             mPid = pid;
   1007             mCallback = callback;
   1008         }
   1009 
   1010         @Override
   1011         public void binderDied() {
   1012             if (DEBUG) {
   1013                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
   1014             }
   1015             onCallbackDied(mPid);
   1016         }
   1017 
   1018         public void notifyDisplayEventAsync(int displayId, int event) {
   1019             try {
   1020                 mCallback.onDisplayEvent(displayId, event);
   1021             } catch (RemoteException ex) {
   1022                 Slog.w(TAG, "Failed to notify process "
   1023                         + mPid + " that displays changed, assuming it died.", ex);
   1024                 binderDied();
   1025             }
   1026         }
   1027     }
   1028 }
   1029