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