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.SensorManager;
     25 import android.hardware.display.DisplayManager;
     26 import android.hardware.display.DisplayManagerGlobal;
     27 import android.hardware.display.DisplayManagerInternal;
     28 import android.hardware.display.DisplayViewport;
     29 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
     30 import android.hardware.display.IDisplayManager;
     31 import android.hardware.display.IDisplayManagerCallback;
     32 import android.hardware.display.IVirtualDisplayCallback;
     33 import android.hardware.display.WifiDisplayStatus;
     34 import android.hardware.input.InputManagerInternal;
     35 import android.media.projection.IMediaProjection;
     36 import android.media.projection.IMediaProjectionManager;
     37 import android.os.Binder;
     38 import android.os.Handler;
     39 import android.os.IBinder;
     40 import android.os.IBinder.DeathRecipient;
     41 import android.os.Looper;
     42 import android.os.Message;
     43 import android.os.PowerManager;
     44 import android.os.Process;
     45 import android.os.RemoteException;
     46 import android.os.ServiceManager;
     47 import android.os.SystemClock;
     48 import android.os.SystemProperties;
     49 import android.os.Trace;
     50 import android.text.TextUtils;
     51 import android.util.Slog;
     52 import android.util.SparseArray;
     53 import android.view.Display;
     54 import android.view.DisplayInfo;
     55 import android.view.Surface;
     56 import android.view.WindowManagerInternal;
     57 
     58 import com.android.server.DisplayThread;
     59 import com.android.server.LocalServices;
     60 import com.android.server.SystemService;
     61 import com.android.server.UiThread;
     62 
     63 import java.io.FileDescriptor;
     64 import java.io.PrintWriter;
     65 import java.util.ArrayList;
     66 import java.util.Arrays;
     67 import java.util.List;
     68 import java.util.concurrent.CopyOnWriteArrayList;
     69 
     70 /**
     71  * Manages attached displays.
     72  * <p>
     73  * The {@link DisplayManagerService} manages the global lifecycle of displays,
     74  * decides how to configure logical displays based on the physical display devices currently
     75  * attached, sends notifications to the system and to applications when the state
     76  * changes, and so on.
     77  * </p><p>
     78  * The display manager service relies on a collection of {@link DisplayAdapter} components,
     79  * for discovering and configuring physical display devices attached to the system.
     80  * There are separate display adapters for each manner that devices are attached:
     81  * one display adapter for built-in local displays, one for simulated non-functional
     82  * displays when the system is headless, one for simulated overlay displays used for
     83  * development, one for wifi displays, etc.
     84  * </p><p>
     85  * Display adapters are only weakly coupled to the display manager service.
     86  * Display adapters communicate changes in display device state to the display manager
     87  * service asynchronously via a {@link DisplayAdapter.Listener} registered
     88  * by the display manager service.  This separation of concerns is important for
     89  * two main reasons.  First, it neatly encapsulates the responsibilities of these
     90  * two classes: display adapters handle individual display devices whereas
     91  * the display manager service handles the global state.  Second, it eliminates
     92  * the potential for deadlocks resulting from asynchronous display device discovery.
     93  * </p>
     94  *
     95  * <h3>Synchronization</h3>
     96  * <p>
     97  * Because the display manager may be accessed by multiple threads, the synchronization
     98  * story gets a little complicated.  In particular, the window manager may call into
     99  * the display manager while holding a surface transaction with the expectation that
    100  * it can apply changes immediately.  Unfortunately, that means we can't just do
    101  * everything asynchronously (*grump*).
    102  * </p><p>
    103  * To make this work, all of the objects that belong to the display manager must
    104  * use the same lock.  We call this lock the synchronization root and it has a unique
    105  * type {@link DisplayManagerService.SyncRoot}.  Methods that require this lock are
    106  * named with the "Locked" suffix.
    107  * </p><p>
    108  * Where things get tricky is that the display manager is not allowed to make
    109  * any potentially reentrant calls, especially into the window manager.  We generally
    110  * avoid this by making all potentially reentrant out-calls asynchronous.
    111  * </p>
    112  */
    113 public final class DisplayManagerService extends SystemService {
    114     private static final String TAG = "DisplayManagerService";
    115     private static final boolean DEBUG = false;
    116 
    117     // When this system property is set to 0, WFD is forcibly disabled on boot.
    118     // When this system property is set to 1, WFD is forcibly enabled on boot.
    119     // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
    120     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
    121 
    122     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
    123 
    124     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
    125     private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
    126     private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
    127     private static final int MSG_REQUEST_TRAVERSAL = 4;
    128     private static final int MSG_UPDATE_VIEWPORT = 5;
    129 
    130     private final Context mContext;
    131     private final DisplayManagerHandler mHandler;
    132     private final Handler mUiHandler;
    133     private final DisplayAdapterListener mDisplayAdapterListener;
    134     private WindowManagerInternal mWindowManagerInternal;
    135     private InputManagerInternal mInputManagerInternal;
    136     private IMediaProjectionManager mProjectionService;
    137 
    138     // The synchronization root for the display manager.
    139     // This lock guards most of the display manager's state.
    140     // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
    141     // into WindowManagerService methods that require mWindowMap while holding this unless you are
    142     // very very sure that no deadlock can occur.
    143     private final SyncRoot mSyncRoot = new SyncRoot();
    144 
    145     // True if in safe mode.
    146     // This option may disable certain display adapters.
    147     public boolean mSafeMode;
    148 
    149     // True if we are in a special boot mode where only core applications and
    150     // services should be started.  This option may disable certain display adapters.
    151     public boolean mOnlyCore;
    152 
    153     // True if the display manager service should pretend there is only one display
    154     // and only tell applications about the existence of the default logical display.
    155     // The display manager can still mirror content to secondary displays but applications
    156     // cannot present unique content on those displays.
    157     // Used for demonstration purposes only.
    158     private final boolean mSingleDisplayDemoMode;
    159 
    160     // All callback records indexed by calling process id.
    161     public final SparseArray<CallbackRecord> mCallbacks =
    162             new SparseArray<CallbackRecord>();
    163 
    164     // List of all currently registered display adapters.
    165     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
    166 
    167     // List of all currently connected display devices.
    168     private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
    169 
    170     // List of all logical displays indexed by logical display id.
    171     private final SparseArray<LogicalDisplay> mLogicalDisplays =
    172             new SparseArray<LogicalDisplay>();
    173     private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
    174 
    175     // List of all display transaction listeners.
    176     private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
    177             new CopyOnWriteArrayList<DisplayTransactionListener>();
    178 
    179     // Display power controller.
    180     private DisplayPowerController mDisplayPowerController;
    181 
    182     // The overall display state, independent of changes that might influence one
    183     // display or another in particular.
    184     private int mGlobalDisplayState = Display.STATE_ON;
    185 
    186     // The overall display brightness.
    187     // For now, this only applies to the built-in display but we may split it up eventually.
    188     private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
    189 
    190     // Set to true when there are pending display changes that have yet to be applied
    191     // to the surface flinger state.
    192     private boolean mPendingTraversal;
    193 
    194     // The Wifi display adapter, or null if not registered.
    195     private WifiDisplayAdapter mWifiDisplayAdapter;
    196 
    197     // The number of active wifi display scan requests.
    198     private int mWifiDisplayScanRequestCount;
    199 
    200     // The virtual display adapter, or null if not registered.
    201     private VirtualDisplayAdapter mVirtualDisplayAdapter;
    202 
    203     // Viewports of the default display and the display that should receive touch
    204     // input from an external source.  Used by the input system.
    205     private final DisplayViewport mDefaultViewport = new DisplayViewport();
    206     private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
    207 
    208     // Persistent data store for all internal settings maintained by the display manager service.
    209     private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
    210 
    211     // Temporary callback list, used when sending display events to applications.
    212     // May be used outside of the lock but only on the handler thread.
    213     private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
    214 
    215     // Temporary display info, used for comparing display configurations.
    216     private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
    217 
    218     // Temporary viewports, used when sending new viewport information to the
    219     // input system.  May be used outside of the lock but only on the handler thread.
    220     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
    221     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
    222 
    223     // Temporary list of deferred work to perform when setting the display state.
    224     // Only used by requestDisplayState.  The field is self-synchronized and only
    225     // intended for use inside of the requestGlobalDisplayStateInternal function.
    226     private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
    227 
    228     public DisplayManagerService(Context context) {
    229         super(context);
    230         mContext = context;
    231         mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
    232         mUiHandler = UiThread.getHandler();
    233         mDisplayAdapterListener = new DisplayAdapterListener();
    234         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
    235 
    236         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
    237         mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
    238     }
    239 
    240     @Override
    241     public void onStart() {
    242         // We need to pre-load the persistent data store so it's ready before the default display
    243         // adapter is up so that we have it's configuration. We could load it lazily, but since
    244         // we're going to have to read it in eventually we may as well do it here rather than after
    245         // we've waited for the diplay to register itself with us.
    246         mPersistentDataStore.loadIfNeeded();
    247         mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
    248 
    249         publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
    250                 true /*allowIsolated*/);
    251         publishLocalService(DisplayManagerInternal.class, new LocalService());
    252         publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
    253     }
    254 
    255     @Override
    256     public void onBootPhase(int phase) {
    257         if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
    258             synchronized (mSyncRoot) {
    259                 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
    260                 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
    261                     long delay = timeout - SystemClock.uptimeMillis();
    262                     if (delay <= 0) {
    263                         throw new RuntimeException("Timeout waiting for default display "
    264                                 + "to be initialized.");
    265                     }
    266                     if (DEBUG) {
    267                         Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
    268                     }
    269                     try {
    270                         mSyncRoot.wait(delay);
    271                     } catch (InterruptedException ex) {
    272                     }
    273                 }
    274             }
    275         }
    276     }
    277 
    278     // TODO: Use dependencies or a boot phase
    279     public void windowManagerAndInputReady() {
    280         synchronized (mSyncRoot) {
    281             mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
    282             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
    283             scheduleTraversalLocked(false);
    284         }
    285     }
    286 
    287     /**
    288      * Called when the system is ready to go.
    289      */
    290     public void systemReady(boolean safeMode, boolean onlyCore) {
    291         synchronized (mSyncRoot) {
    292             mSafeMode = safeMode;
    293             mOnlyCore = onlyCore;
    294         }
    295 
    296         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
    297     }
    298 
    299     private void registerDisplayTransactionListenerInternal(
    300             DisplayTransactionListener listener) {
    301         // List is self-synchronized copy-on-write.
    302         mDisplayTransactionListeners.add(listener);
    303     }
    304 
    305     private void unregisterDisplayTransactionListenerInternal(
    306             DisplayTransactionListener listener) {
    307         // List is self-synchronized copy-on-write.
    308         mDisplayTransactionListeners.remove(listener);
    309     }
    310 
    311     private void setDisplayInfoOverrideFromWindowManagerInternal(
    312             int displayId, DisplayInfo info) {
    313         synchronized (mSyncRoot) {
    314             LogicalDisplay display = mLogicalDisplays.get(displayId);
    315             if (display != null) {
    316                 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
    317                     sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
    318                     scheduleTraversalLocked(false);
    319                 }
    320             }
    321         }
    322     }
    323 
    324     private void performTraversalInTransactionFromWindowManagerInternal() {
    325         synchronized (mSyncRoot) {
    326             if (!mPendingTraversal) {
    327                 return;
    328             }
    329             mPendingTraversal = false;
    330 
    331             performTraversalInTransactionLocked();
    332         }
    333 
    334         // List is self-synchronized copy-on-write.
    335         for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
    336             listener.onDisplayTransaction();
    337         }
    338     }
    339 
    340     private void requestGlobalDisplayStateInternal(int state, int brightness) {
    341         if (state == Display.STATE_UNKNOWN) {
    342             state = Display.STATE_ON;
    343         }
    344         if (state == Display.STATE_OFF) {
    345             brightness = PowerManager.BRIGHTNESS_OFF;
    346         } else if (brightness < 0) {
    347             brightness = PowerManager.BRIGHTNESS_DEFAULT;
    348         } else if (brightness > PowerManager.BRIGHTNESS_ON) {
    349             brightness = PowerManager.BRIGHTNESS_ON;
    350         }
    351 
    352         synchronized (mTempDisplayStateWorkQueue) {
    353             try {
    354                 // Update the display state within the lock.
    355                 // Note that we do not need to schedule traversals here although it
    356                 // may happen as a side-effect of displays changing state.
    357                 synchronized (mSyncRoot) {
    358                     if (mGlobalDisplayState == state
    359                             && mGlobalDisplayBrightness == brightness) {
    360                         return; // no change
    361                     }
    362 
    363                     Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
    364                             + Display.stateToString(state)
    365                             + ", brightness=" + brightness + ")");
    366                     mGlobalDisplayState = state;
    367                     mGlobalDisplayBrightness = brightness;
    368                     applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
    369                 }
    370 
    371                 // Setting the display power state can take hundreds of milliseconds
    372                 // to complete so we defer the most expensive part of the work until
    373                 // after we have exited the critical section to avoid blocking other
    374                 // threads for a long time.
    375                 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
    376                     mTempDisplayStateWorkQueue.get(i).run();
    377                 }
    378                 Trace.traceEnd(Trace.TRACE_TAG_POWER);
    379             } finally {
    380                 mTempDisplayStateWorkQueue.clear();
    381             }
    382         }
    383     }
    384 
    385     private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
    386         synchronized (mSyncRoot) {
    387             LogicalDisplay display = mLogicalDisplays.get(displayId);
    388             if (display != null) {
    389                 DisplayInfo info = display.getDisplayInfoLocked();
    390                 if (info.hasAccess(callingUid)) {
    391                     return info;
    392                 }
    393             }
    394             return null;
    395         }
    396     }
    397 
    398     private int[] getDisplayIdsInternal(int callingUid) {
    399         synchronized (mSyncRoot) {
    400             final int count = mLogicalDisplays.size();
    401             int[] displayIds = new int[count];
    402             int n = 0;
    403             for (int i = 0; i < count; i++) {
    404                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
    405                 DisplayInfo info = display.getDisplayInfoLocked();
    406                 if (info.hasAccess(callingUid)) {
    407                     displayIds[n++] = mLogicalDisplays.keyAt(i);
    408                 }
    409             }
    410             if (n != count) {
    411                 displayIds = Arrays.copyOfRange(displayIds, 0, n);
    412             }
    413             return displayIds;
    414         }
    415     }
    416 
    417     private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
    418         synchronized (mSyncRoot) {
    419             if (mCallbacks.get(callingPid) != null) {
    420                 throw new SecurityException("The calling process has already "
    421                         + "registered an IDisplayManagerCallback.");
    422             }
    423 
    424             CallbackRecord record = new CallbackRecord(callingPid, callback);
    425             try {
    426                 IBinder binder = callback.asBinder();
    427                 binder.linkToDeath(record, 0);
    428             } catch (RemoteException ex) {
    429                 // give up
    430                 throw new RuntimeException(ex);
    431             }
    432 
    433             mCallbacks.put(callingPid, record);
    434         }
    435     }
    436 
    437     private void onCallbackDied(CallbackRecord record) {
    438         synchronized (mSyncRoot) {
    439             mCallbacks.remove(record.mPid);
    440             stopWifiDisplayScanLocked(record);
    441         }
    442     }
    443 
    444     private void startWifiDisplayScanInternal(int callingPid) {
    445         synchronized (mSyncRoot) {
    446             CallbackRecord record = mCallbacks.get(callingPid);
    447             if (record == null) {
    448                 throw new IllegalStateException("The calling process has not "
    449                         + "registered an IDisplayManagerCallback.");
    450             }
    451             startWifiDisplayScanLocked(record);
    452         }
    453     }
    454 
    455     private void startWifiDisplayScanLocked(CallbackRecord record) {
    456         if (!record.mWifiDisplayScanRequested) {
    457             record.mWifiDisplayScanRequested = true;
    458             if (mWifiDisplayScanRequestCount++ == 0) {
    459                 if (mWifiDisplayAdapter != null) {
    460                     mWifiDisplayAdapter.requestStartScanLocked();
    461                 }
    462             }
    463         }
    464     }
    465 
    466     private void stopWifiDisplayScanInternal(int callingPid) {
    467         synchronized (mSyncRoot) {
    468             CallbackRecord record = mCallbacks.get(callingPid);
    469             if (record == null) {
    470                 throw new IllegalStateException("The calling process has not "
    471                         + "registered an IDisplayManagerCallback.");
    472             }
    473             stopWifiDisplayScanLocked(record);
    474         }
    475     }
    476 
    477     private void stopWifiDisplayScanLocked(CallbackRecord record) {
    478         if (record.mWifiDisplayScanRequested) {
    479             record.mWifiDisplayScanRequested = false;
    480             if (--mWifiDisplayScanRequestCount == 0) {
    481                 if (mWifiDisplayAdapter != null) {
    482                     mWifiDisplayAdapter.requestStopScanLocked();
    483                 }
    484             } else if (mWifiDisplayScanRequestCount < 0) {
    485                 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
    486                         + mWifiDisplayScanRequestCount);
    487                 mWifiDisplayScanRequestCount = 0;
    488             }
    489         }
    490     }
    491 
    492     private void connectWifiDisplayInternal(String address) {
    493         synchronized (mSyncRoot) {
    494             if (mWifiDisplayAdapter != null) {
    495                 mWifiDisplayAdapter.requestConnectLocked(address);
    496             }
    497         }
    498     }
    499 
    500     private void pauseWifiDisplayInternal() {
    501         synchronized (mSyncRoot) {
    502             if (mWifiDisplayAdapter != null) {
    503                 mWifiDisplayAdapter.requestPauseLocked();
    504             }
    505         }
    506     }
    507 
    508     private void resumeWifiDisplayInternal() {
    509         synchronized (mSyncRoot) {
    510             if (mWifiDisplayAdapter != null) {
    511                 mWifiDisplayAdapter.requestResumeLocked();
    512             }
    513         }
    514     }
    515 
    516     private void disconnectWifiDisplayInternal() {
    517         synchronized (mSyncRoot) {
    518             if (mWifiDisplayAdapter != null) {
    519                 mWifiDisplayAdapter.requestDisconnectLocked();
    520             }
    521         }
    522     }
    523 
    524     private void renameWifiDisplayInternal(String address, String alias) {
    525         synchronized (mSyncRoot) {
    526             if (mWifiDisplayAdapter != null) {
    527                 mWifiDisplayAdapter.requestRenameLocked(address, alias);
    528             }
    529         }
    530     }
    531 
    532     private void forgetWifiDisplayInternal(String address) {
    533         synchronized (mSyncRoot) {
    534             if (mWifiDisplayAdapter != null) {
    535                 mWifiDisplayAdapter.requestForgetLocked(address);
    536             }
    537         }
    538     }
    539 
    540     private WifiDisplayStatus getWifiDisplayStatusInternal() {
    541         synchronized (mSyncRoot) {
    542             if (mWifiDisplayAdapter != null) {
    543                 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
    544             }
    545             return new WifiDisplayStatus();
    546         }
    547     }
    548 
    549     private void requestColorModeInternal(int displayId, int colorMode) {
    550         synchronized (mSyncRoot) {
    551             LogicalDisplay display = mLogicalDisplays.get(displayId);
    552             if (display != null &&
    553                     display.getRequestedColorModeLocked() != colorMode) {
    554                 display.setRequestedColorModeLocked(colorMode);
    555                 scheduleTraversalLocked(false);
    556             }
    557         }
    558     }
    559 
    560     private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
    561             IMediaProjection projection, int callingUid, String packageName,
    562             String name, int width, int height, int densityDpi, Surface surface, int flags) {
    563         synchronized (mSyncRoot) {
    564             if (mVirtualDisplayAdapter == null) {
    565                 Slog.w(TAG, "Rejecting request to create private virtual display "
    566                         + "because the virtual display adapter is not available.");
    567                 return -1;
    568             }
    569 
    570             DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
    571                     callback, projection, callingUid, packageName,
    572                     name, width, height, densityDpi, surface, flags);
    573             if (device == null) {
    574                 return -1;
    575             }
    576 
    577             handleDisplayDeviceAddedLocked(device);
    578             LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
    579             if (display != null) {
    580                 return display.getDisplayIdLocked();
    581             }
    582 
    583             // Something weird happened and the logical display was not created.
    584             Slog.w(TAG, "Rejecting request to create virtual display "
    585                     + "because the logical display was not created.");
    586             mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
    587             handleDisplayDeviceRemovedLocked(device);
    588         }
    589         return -1;
    590     }
    591 
    592     private void resizeVirtualDisplayInternal(IBinder appToken,
    593             int width, int height, int densityDpi) {
    594         synchronized (mSyncRoot) {
    595             if (mVirtualDisplayAdapter == null) {
    596                 return;
    597             }
    598 
    599             mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi);
    600         }
    601     }
    602 
    603     private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
    604         synchronized (mSyncRoot) {
    605             if (mVirtualDisplayAdapter == null) {
    606                 return;
    607             }
    608 
    609             mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
    610         }
    611     }
    612 
    613     private void releaseVirtualDisplayInternal(IBinder appToken) {
    614         synchronized (mSyncRoot) {
    615             if (mVirtualDisplayAdapter == null) {
    616                 return;
    617             }
    618 
    619             DisplayDevice device =
    620                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
    621             if (device != null) {
    622                 handleDisplayDeviceRemovedLocked(device);
    623             }
    624         }
    625     }
    626 
    627     private void registerDefaultDisplayAdapter() {
    628         // Register default display adapter.
    629         synchronized (mSyncRoot) {
    630             registerDisplayAdapterLocked(new LocalDisplayAdapter(
    631                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
    632         }
    633     }
    634 
    635     private void registerAdditionalDisplayAdapters() {
    636         synchronized (mSyncRoot) {
    637             if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
    638                 registerOverlayDisplayAdapterLocked();
    639                 registerWifiDisplayAdapterLocked();
    640                 registerVirtualDisplayAdapterLocked();
    641             }
    642         }
    643     }
    644 
    645     private void registerOverlayDisplayAdapterLocked() {
    646         registerDisplayAdapterLocked(new OverlayDisplayAdapter(
    647                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
    648     }
    649 
    650     private void registerWifiDisplayAdapterLocked() {
    651         if (mContext.getResources().getBoolean(
    652                 com.android.internal.R.bool.config_enableWifiDisplay)
    653                 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
    654             mWifiDisplayAdapter = new WifiDisplayAdapter(
    655                     mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
    656                     mPersistentDataStore);
    657             registerDisplayAdapterLocked(mWifiDisplayAdapter);
    658         }
    659     }
    660 
    661     private void registerVirtualDisplayAdapterLocked() {
    662         mVirtualDisplayAdapter = new VirtualDisplayAdapter(
    663                 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
    664         registerDisplayAdapterLocked(mVirtualDisplayAdapter);
    665     }
    666 
    667     private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
    668         // In safe mode, we disable non-essential display adapters to give the user
    669         // an opportunity to fix broken settings or other problems that might affect
    670         // system stability.
    671         // In only-core mode, we disable non-essential display adapters to minimize
    672         // the number of dependencies that are started while in this mode and to
    673         // prevent problems that might occur due to the device being encrypted.
    674         return !mSafeMode && !mOnlyCore;
    675     }
    676 
    677     private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
    678         mDisplayAdapters.add(adapter);
    679         adapter.registerLocked();
    680     }
    681 
    682     private void handleDisplayDeviceAdded(DisplayDevice device) {
    683         synchronized (mSyncRoot) {
    684             handleDisplayDeviceAddedLocked(device);
    685         }
    686     }
    687 
    688     private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
    689         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    690         if (mDisplayDevices.contains(device)) {
    691             Slog.w(TAG, "Attempted to add already added display device: " + info);
    692             return;
    693         }
    694 
    695         Slog.i(TAG, "Display device added: " + info);
    696         device.mDebugLastLoggedDeviceInfo = info;
    697 
    698         mDisplayDevices.add(device);
    699         LogicalDisplay display = addLogicalDisplayLocked(device);
    700         Runnable work = updateDisplayStateLocked(device);
    701         if (work != null) {
    702             work.run();
    703         }
    704         if (display != null && display.getPrimaryDisplayDeviceLocked() == device) {
    705             int colorMode = mPersistentDataStore.getColorMode(device);
    706             display.setRequestedColorModeLocked(colorMode);
    707         }
    708         scheduleTraversalLocked(false);
    709     }
    710 
    711     private void handleDisplayDeviceChanged(DisplayDevice device) {
    712         synchronized (mSyncRoot) {
    713             DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    714             if (!mDisplayDevices.contains(device)) {
    715                 Slog.w(TAG, "Attempted to change non-existent display device: " + info);
    716                 return;
    717             }
    718 
    719             int diff = device.mDebugLastLoggedDeviceInfo.diff(info);
    720             if (diff == DisplayDeviceInfo.DIFF_STATE) {
    721                 Slog.i(TAG, "Display device changed state: \"" + info.name
    722                         + "\", " + Display.stateToString(info.state));
    723             } else if (diff != 0) {
    724                 Slog.i(TAG, "Display device changed: " + info);
    725             }
    726             if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) {
    727                 try {
    728                     mPersistentDataStore.setColorMode(device, info.colorMode);
    729                 } finally {
    730                     mPersistentDataStore.saveIfNeeded();
    731                 }
    732             }
    733             device.mDebugLastLoggedDeviceInfo = info;
    734 
    735             device.applyPendingDisplayDeviceInfoChangesLocked();
    736             if (updateLogicalDisplaysLocked()) {
    737                 scheduleTraversalLocked(false);
    738             }
    739         }
    740     }
    741 
    742     private void handleDisplayDeviceRemoved(DisplayDevice device) {
    743         synchronized (mSyncRoot) {
    744             handleDisplayDeviceRemovedLocked(device);
    745         }
    746     }
    747 
    748     private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
    749         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    750         if (!mDisplayDevices.remove(device)) {
    751             Slog.w(TAG, "Attempted to remove non-existent display device: " + info);
    752             return;
    753         }
    754 
    755         Slog.i(TAG, "Display device removed: " + info);
    756         device.mDebugLastLoggedDeviceInfo = info;
    757 
    758         updateLogicalDisplaysLocked();
    759         scheduleTraversalLocked(false);
    760     }
    761 
    762     private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
    763         final int count = mDisplayDevices.size();
    764         for (int i = 0; i < count; i++) {
    765             DisplayDevice device = mDisplayDevices.get(i);
    766             Runnable runnable = updateDisplayStateLocked(device);
    767             if (runnable != null) {
    768                 workQueue.add(runnable);
    769             }
    770         }
    771     }
    772 
    773     private Runnable updateDisplayStateLocked(DisplayDevice device) {
    774         // Blank or unblank the display immediately to match the state requested
    775         // by the display power controller (if known).
    776         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    777         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
    778             return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
    779         }
    780         return null;
    781     }
    782 
    783     // Adds a new logical display based on the given display device.
    784     // Sends notifications if needed.
    785     private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
    786         DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
    787         boolean isDefault = (deviceInfo.flags
    788                 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
    789         if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
    790             Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
    791             isDefault = false;
    792         }
    793 
    794         if (!isDefault && mSingleDisplayDemoMode) {
    795             Slog.i(TAG, "Not creating a logical display for a secondary display "
    796                     + " because single display demo mode is enabled: " + deviceInfo);
    797             return null;
    798         }
    799 
    800         final int displayId = assignDisplayIdLocked(isDefault);
    801         final int layerStack = assignLayerStackLocked(displayId);
    802 
    803         LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
    804         display.updateLocked(mDisplayDevices);
    805         if (!display.isValidLocked()) {
    806             // This should never happen currently.
    807             Slog.w(TAG, "Ignoring display device because the logical display "
    808                     + "created from it was not considered valid: " + deviceInfo);
    809             return null;
    810         }
    811 
    812         mLogicalDisplays.put(displayId, display);
    813 
    814         // Wake up waitForDefaultDisplay.
    815         if (isDefault) {
    816             mSyncRoot.notifyAll();
    817         }
    818 
    819         sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
    820         return display;
    821     }
    822 
    823     private int assignDisplayIdLocked(boolean isDefault) {
    824         return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
    825     }
    826 
    827     private int assignLayerStackLocked(int displayId) {
    828         // Currently layer stacks and display ids are the same.
    829         // This need not be the case.
    830         return displayId;
    831     }
    832 
    833     // Updates all existing logical displays given the current set of display devices.
    834     // Removes invalid logical displays.
    835     // Sends notifications if needed.
    836     private boolean updateLogicalDisplaysLocked() {
    837         boolean changed = false;
    838         for (int i = mLogicalDisplays.size(); i-- > 0; ) {
    839             final int displayId = mLogicalDisplays.keyAt(i);
    840             LogicalDisplay display = mLogicalDisplays.valueAt(i);
    841 
    842             mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
    843             display.updateLocked(mDisplayDevices);
    844             if (!display.isValidLocked()) {
    845                 mLogicalDisplays.removeAt(i);
    846                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
    847                 changed = true;
    848             } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
    849                 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
    850                 changed = true;
    851             }
    852         }
    853         return changed;
    854     }
    855 
    856     private void performTraversalInTransactionLocked() {
    857         // Clear all viewports before configuring displays so that we can keep
    858         // track of which ones we have configured.
    859         clearViewportsLocked();
    860 
    861         // Configure each display device.
    862         final int count = mDisplayDevices.size();
    863         for (int i = 0; i < count; i++) {
    864             DisplayDevice device = mDisplayDevices.get(i);
    865             configureDisplayInTransactionLocked(device);
    866             device.performTraversalInTransactionLocked();
    867         }
    868 
    869         // Tell the input system about these new viewports.
    870         if (mInputManagerInternal != null) {
    871             mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
    872         }
    873     }
    874 
    875     private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
    876             float requestedRefreshRate, int requestedModeId, boolean inTraversal) {
    877         synchronized (mSyncRoot) {
    878             LogicalDisplay display = mLogicalDisplays.get(displayId);
    879             if (display == null) {
    880                 return;
    881             }
    882             if (display.hasContentLocked() != hasContent) {
    883                 if (DEBUG) {
    884                     Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
    885                             + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
    886                 }
    887 
    888                 display.setHasContentLocked(hasContent);
    889                 scheduleTraversalLocked(inTraversal);
    890             }
    891             if (requestedModeId == 0 && requestedRefreshRate != 0) {
    892                 // Scan supported modes returned by display.getInfo() to find a mode with the same
    893                 // size as the default display mode but with the specified refresh rate instead.
    894                 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
    895                         requestedRefreshRate);
    896             }
    897             if (display.getRequestedModeIdLocked() != requestedModeId) {
    898                 if (DEBUG) {
    899                     Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId);
    900                 }
    901                 display.setRequestedModeIdLocked(requestedModeId);
    902                 scheduleTraversalLocked(inTraversal);
    903             }
    904         }
    905     }
    906 
    907     private void setDisplayOffsetsInternal(int displayId, int x, int y) {
    908         synchronized (mSyncRoot) {
    909             LogicalDisplay display = mLogicalDisplays.get(displayId);
    910             if (display == null) {
    911                 return;
    912             }
    913             if (display.getDisplayOffsetXLocked() != x
    914                     || display.getDisplayOffsetYLocked() != y) {
    915                 if (DEBUG) {
    916                     Slog.d(TAG, "Display " + displayId + " burn-in offset set to ("
    917                             + x + ", " + y + ")");
    918                 }
    919                 display.setDisplayOffsetsLocked(x, y);
    920                 scheduleTraversalLocked(false);
    921             }
    922         }
    923     }
    924 
    925     private void clearViewportsLocked() {
    926         mDefaultViewport.valid = false;
    927         mExternalTouchViewport.valid = false;
    928     }
    929 
    930     private void configureDisplayInTransactionLocked(DisplayDevice device) {
    931         final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    932         final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
    933 
    934         // Find the logical display that the display device is showing.
    935         // Certain displays only ever show their own content.
    936         LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
    937         if (!ownContent) {
    938             if (display != null && !display.hasContentLocked()) {
    939                 // If the display does not have any content of its own, then
    940                 // automatically mirror the default logical display contents.
    941                 display = null;
    942             }
    943             if (display == null) {
    944                 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
    945             }
    946         }
    947 
    948         // Apply the logical display configuration to the display device.
    949         if (display == null) {
    950             // TODO: no logical display for the device, blank it
    951             Slog.w(TAG, "Missing logical display to use for physical display device: "
    952                     + device.getDisplayDeviceInfoLocked());
    953             return;
    954         }
    955         display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
    956 
    957         // Update the viewports if needed.
    958         if (!mDefaultViewport.valid
    959                 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
    960             setViewportLocked(mDefaultViewport, display, device);
    961         }
    962         if (!mExternalTouchViewport.valid
    963                 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
    964             setViewportLocked(mExternalTouchViewport, display, device);
    965         }
    966     }
    967 
    968     private static void setViewportLocked(DisplayViewport viewport,
    969             LogicalDisplay display, DisplayDevice device) {
    970         viewport.valid = true;
    971         viewport.displayId = display.getDisplayIdLocked();
    972         device.populateViewportLocked(viewport);
    973     }
    974 
    975     private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
    976         final int count = mLogicalDisplays.size();
    977         for (int i = 0; i < count; i++) {
    978             LogicalDisplay display = mLogicalDisplays.valueAt(i);
    979             if (display.getPrimaryDisplayDeviceLocked() == device) {
    980                 return display;
    981             }
    982         }
    983         return null;
    984     }
    985 
    986     private void sendDisplayEventLocked(int displayId, int event) {
    987         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
    988         mHandler.sendMessage(msg);
    989     }
    990 
    991     // Requests that performTraversalsInTransactionFromWindowManager be called at a
    992     // later time to apply changes to surfaces and displays.
    993     private void scheduleTraversalLocked(boolean inTraversal) {
    994         if (!mPendingTraversal && mWindowManagerInternal != null) {
    995             mPendingTraversal = true;
    996             if (!inTraversal) {
    997                 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
    998             }
    999         }
   1000     }
   1001 
   1002     // Runs on Handler thread.
   1003     // Delivers display event notifications to callbacks.
   1004     private void deliverDisplayEvent(int displayId, int event) {
   1005         if (DEBUG) {
   1006             Slog.d(TAG, "Delivering display event: displayId="
   1007                     + displayId + ", event=" + event);
   1008         }
   1009 
   1010         // Grab the lock and copy the callbacks.
   1011         final int count;
   1012         synchronized (mSyncRoot) {
   1013             count = mCallbacks.size();
   1014             mTempCallbacks.clear();
   1015             for (int i = 0; i < count; i++) {
   1016                 mTempCallbacks.add(mCallbacks.valueAt(i));
   1017             }
   1018         }
   1019 
   1020         // After releasing the lock, send the notifications out.
   1021         for (int i = 0; i < count; i++) {
   1022             mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
   1023         }
   1024         mTempCallbacks.clear();
   1025     }
   1026 
   1027     private IMediaProjectionManager getProjectionService() {
   1028         if (mProjectionService == null) {
   1029             IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
   1030             mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
   1031         }
   1032         return mProjectionService;
   1033     }
   1034 
   1035     private void dumpInternal(PrintWriter pw) {
   1036         pw.println("DISPLAY MANAGER (dumpsys display)");
   1037 
   1038         synchronized (mSyncRoot) {
   1039             pw.println("  mOnlyCode=" + mOnlyCore);
   1040             pw.println("  mSafeMode=" + mSafeMode);
   1041             pw.println("  mPendingTraversal=" + mPendingTraversal);
   1042             pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
   1043             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
   1044             pw.println("  mDefaultViewport=" + mDefaultViewport);
   1045             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
   1046             pw.println("  mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
   1047             pw.println("  mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
   1048 
   1049             IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
   1050             ipw.increaseIndent();
   1051 
   1052             pw.println();
   1053             pw.println("Display Adapters: size=" + mDisplayAdapters.size());
   1054             for (DisplayAdapter adapter : mDisplayAdapters) {
   1055                 pw.println("  " + adapter.getName());
   1056                 adapter.dumpLocked(ipw);
   1057             }
   1058 
   1059             pw.println();
   1060             pw.println("Display Devices: size=" + mDisplayDevices.size());
   1061             for (DisplayDevice device : mDisplayDevices) {
   1062                 pw.println("  " + device.getDisplayDeviceInfoLocked());
   1063                 device.dumpLocked(ipw);
   1064             }
   1065 
   1066             final int logicalDisplayCount = mLogicalDisplays.size();
   1067             pw.println();
   1068             pw.println("Logical Displays: size=" + logicalDisplayCount);
   1069             for (int i = 0; i < logicalDisplayCount; i++) {
   1070                 int displayId = mLogicalDisplays.keyAt(i);
   1071                 LogicalDisplay display = mLogicalDisplays.valueAt(i);
   1072                 pw.println("  Display " + displayId + ":");
   1073                 display.dumpLocked(ipw);
   1074             }
   1075 
   1076             final int callbackCount = mCallbacks.size();
   1077             pw.println();
   1078             pw.println("Callbacks: size=" + callbackCount);
   1079             for (int i = 0; i < callbackCount; i++) {
   1080                 CallbackRecord callback = mCallbacks.valueAt(i);
   1081                 pw.println("  " + i + ": mPid=" + callback.mPid
   1082                         + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
   1083             }
   1084 
   1085             if (mDisplayPowerController != null) {
   1086                 mDisplayPowerController.dump(pw);
   1087             }
   1088 
   1089             pw.println();
   1090             mPersistentDataStore.dump(pw);
   1091         }
   1092     }
   1093 
   1094     /**
   1095      * This is the object that everything in the display manager locks on.
   1096      * We make it an inner class within the {@link DisplayManagerService} to so that it is
   1097      * clear that the object belongs to the display manager service and that it is
   1098      * a unique object with a special purpose.
   1099      */
   1100     public static final class SyncRoot {
   1101     }
   1102 
   1103     private final class DisplayManagerHandler extends Handler {
   1104         public DisplayManagerHandler(Looper looper) {
   1105             super(looper, null, true /*async*/);
   1106         }
   1107 
   1108         @Override
   1109         public void handleMessage(Message msg) {
   1110             switch (msg.what) {
   1111                 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
   1112                     registerDefaultDisplayAdapter();
   1113                     break;
   1114 
   1115                 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
   1116                     registerAdditionalDisplayAdapters();
   1117                     break;
   1118 
   1119                 case MSG_DELIVER_DISPLAY_EVENT:
   1120                     deliverDisplayEvent(msg.arg1, msg.arg2);
   1121                     break;
   1122 
   1123                 case MSG_REQUEST_TRAVERSAL:
   1124                     mWindowManagerInternal.requestTraversalFromDisplayManager();
   1125                     break;
   1126 
   1127                 case MSG_UPDATE_VIEWPORT: {
   1128                     synchronized (mSyncRoot) {
   1129                         mTempDefaultViewport.copyFrom(mDefaultViewport);
   1130                         mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
   1131                     }
   1132                     mInputManagerInternal.setDisplayViewports(
   1133                             mTempDefaultViewport, mTempExternalTouchViewport);
   1134                     break;
   1135                 }
   1136             }
   1137         }
   1138     }
   1139 
   1140     private final class DisplayAdapterListener implements DisplayAdapter.Listener {
   1141         @Override
   1142         public void onDisplayDeviceEvent(DisplayDevice device, int event) {
   1143             switch (event) {
   1144                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
   1145                     handleDisplayDeviceAdded(device);
   1146                     break;
   1147 
   1148                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
   1149                     handleDisplayDeviceChanged(device);
   1150                     break;
   1151 
   1152                 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
   1153                     handleDisplayDeviceRemoved(device);
   1154                     break;
   1155             }
   1156         }
   1157 
   1158         @Override
   1159         public void onTraversalRequested() {
   1160             synchronized (mSyncRoot) {
   1161                 scheduleTraversalLocked(false);
   1162             }
   1163         }
   1164     }
   1165 
   1166     private final class CallbackRecord implements DeathRecipient {
   1167         public final int mPid;
   1168         private final IDisplayManagerCallback mCallback;
   1169 
   1170         public boolean mWifiDisplayScanRequested;
   1171 
   1172         public CallbackRecord(int pid, IDisplayManagerCallback callback) {
   1173             mPid = pid;
   1174             mCallback = callback;
   1175         }
   1176 
   1177         @Override
   1178         public void binderDied() {
   1179             if (DEBUG) {
   1180                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
   1181             }
   1182             onCallbackDied(this);
   1183         }
   1184 
   1185         public void notifyDisplayEventAsync(int displayId, int event) {
   1186             try {
   1187                 mCallback.onDisplayEvent(displayId, event);
   1188             } catch (RemoteException ex) {
   1189                 Slog.w(TAG, "Failed to notify process "
   1190                         + mPid + " that displays changed, assuming it died.", ex);
   1191                 binderDied();
   1192             }
   1193         }
   1194     }
   1195 
   1196     private final class BinderService extends IDisplayManager.Stub {
   1197         /**
   1198          * Returns information about the specified logical display.
   1199          *
   1200          * @param displayId The logical display id.
   1201          * @return The logical display info, or null if the display does not exist.  The
   1202          * returned object must be treated as immutable.
   1203          */
   1204         @Override // Binder call
   1205         public DisplayInfo getDisplayInfo(int displayId) {
   1206             final int callingUid = Binder.getCallingUid();
   1207             final long token = Binder.clearCallingIdentity();
   1208             try {
   1209                 return getDisplayInfoInternal(displayId, callingUid);
   1210             } finally {
   1211                 Binder.restoreCallingIdentity(token);
   1212             }
   1213         }
   1214 
   1215         /**
   1216          * Returns the list of all display ids.
   1217          */
   1218         @Override // Binder call
   1219         public int[] getDisplayIds() {
   1220             final int callingUid = Binder.getCallingUid();
   1221             final long token = Binder.clearCallingIdentity();
   1222             try {
   1223                 return getDisplayIdsInternal(callingUid);
   1224             } finally {
   1225                 Binder.restoreCallingIdentity(token);
   1226             }
   1227         }
   1228 
   1229         @Override // Binder call
   1230         public void registerCallback(IDisplayManagerCallback callback) {
   1231             if (callback == null) {
   1232                 throw new IllegalArgumentException("listener must not be null");
   1233             }
   1234 
   1235             final int callingPid = Binder.getCallingPid();
   1236             final long token = Binder.clearCallingIdentity();
   1237             try {
   1238                 registerCallbackInternal(callback, callingPid);
   1239             } finally {
   1240                 Binder.restoreCallingIdentity(token);
   1241             }
   1242         }
   1243 
   1244         @Override // Binder call
   1245         public void startWifiDisplayScan() {
   1246             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1247                     "Permission required to start wifi display scans");
   1248 
   1249             final int callingPid = Binder.getCallingPid();
   1250             final long token = Binder.clearCallingIdentity();
   1251             try {
   1252                 startWifiDisplayScanInternal(callingPid);
   1253             } finally {
   1254                 Binder.restoreCallingIdentity(token);
   1255             }
   1256         }
   1257 
   1258         @Override // Binder call
   1259         public void stopWifiDisplayScan() {
   1260             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1261                     "Permission required to stop wifi display scans");
   1262 
   1263             final int callingPid = Binder.getCallingPid();
   1264             final long token = Binder.clearCallingIdentity();
   1265             try {
   1266                 stopWifiDisplayScanInternal(callingPid);
   1267             } finally {
   1268                 Binder.restoreCallingIdentity(token);
   1269             }
   1270         }
   1271 
   1272         @Override // Binder call
   1273         public void connectWifiDisplay(String address) {
   1274             if (address == null) {
   1275                 throw new IllegalArgumentException("address must not be null");
   1276             }
   1277             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1278                     "Permission required to connect to a wifi display");
   1279 
   1280             final long token = Binder.clearCallingIdentity();
   1281             try {
   1282                 connectWifiDisplayInternal(address);
   1283             } finally {
   1284                 Binder.restoreCallingIdentity(token);
   1285             }
   1286         }
   1287 
   1288         @Override // Binder call
   1289         public void disconnectWifiDisplay() {
   1290             // This request does not require special permissions.
   1291             // Any app can request disconnection from the currently active wifi display.
   1292             // This exception should no longer be needed once wifi display control moves
   1293             // to the media router service.
   1294 
   1295             final long token = Binder.clearCallingIdentity();
   1296             try {
   1297                 disconnectWifiDisplayInternal();
   1298             } finally {
   1299                 Binder.restoreCallingIdentity(token);
   1300             }
   1301         }
   1302 
   1303         @Override // Binder call
   1304         public void renameWifiDisplay(String address, String alias) {
   1305             if (address == null) {
   1306                 throw new IllegalArgumentException("address must not be null");
   1307             }
   1308             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1309                     "Permission required to rename to a wifi display");
   1310 
   1311             final long token = Binder.clearCallingIdentity();
   1312             try {
   1313                 renameWifiDisplayInternal(address, alias);
   1314             } finally {
   1315                 Binder.restoreCallingIdentity(token);
   1316             }
   1317         }
   1318 
   1319         @Override // Binder call
   1320         public void forgetWifiDisplay(String address) {
   1321             if (address == null) {
   1322                 throw new IllegalArgumentException("address must not be null");
   1323             }
   1324             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1325                     "Permission required to forget to a wifi display");
   1326 
   1327             final long token = Binder.clearCallingIdentity();
   1328             try {
   1329                 forgetWifiDisplayInternal(address);
   1330             } finally {
   1331                 Binder.restoreCallingIdentity(token);
   1332             }
   1333         }
   1334 
   1335         @Override // Binder call
   1336         public void pauseWifiDisplay() {
   1337             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1338                     "Permission required to pause a wifi display session");
   1339 
   1340             final long token = Binder.clearCallingIdentity();
   1341             try {
   1342                 pauseWifiDisplayInternal();
   1343             } finally {
   1344                 Binder.restoreCallingIdentity(token);
   1345             }
   1346         }
   1347 
   1348         @Override // Binder call
   1349         public void resumeWifiDisplay() {
   1350             mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
   1351                     "Permission required to resume a wifi display session");
   1352 
   1353             final long token = Binder.clearCallingIdentity();
   1354             try {
   1355                 resumeWifiDisplayInternal();
   1356             } finally {
   1357                 Binder.restoreCallingIdentity(token);
   1358             }
   1359         }
   1360 
   1361         @Override // Binder call
   1362         public WifiDisplayStatus getWifiDisplayStatus() {
   1363             // This request does not require special permissions.
   1364             // Any app can get information about available wifi displays.
   1365 
   1366             final long token = Binder.clearCallingIdentity();
   1367             try {
   1368                 return getWifiDisplayStatusInternal();
   1369             } finally {
   1370                 Binder.restoreCallingIdentity(token);
   1371             }
   1372         }
   1373 
   1374         @Override // Binder call
   1375         public void requestColorMode(int displayId, int colorMode) {
   1376             mContext.enforceCallingOrSelfPermission(
   1377                     Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE,
   1378                     "Permission required to change the display color mode");
   1379             final long token = Binder.clearCallingIdentity();
   1380             try {
   1381                 requestColorModeInternal(displayId, colorMode);
   1382             } finally {
   1383                 Binder.restoreCallingIdentity(token);
   1384             }
   1385         }
   1386 
   1387         @Override // Binder call
   1388         public int createVirtualDisplay(IVirtualDisplayCallback callback,
   1389                 IMediaProjection projection, String packageName, String name,
   1390                 int width, int height, int densityDpi, Surface surface, int flags) {
   1391             final int callingUid = Binder.getCallingUid();
   1392             if (!validatePackageName(callingUid, packageName)) {
   1393                 throw new SecurityException("packageName must match the calling uid");
   1394             }
   1395             if (callback == null) {
   1396                 throw new IllegalArgumentException("appToken must not be null");
   1397             }
   1398             if (TextUtils.isEmpty(name)) {
   1399                 throw new IllegalArgumentException("name must be non-null and non-empty");
   1400             }
   1401             if (width <= 0 || height <= 0 || densityDpi <= 0) {
   1402                 throw new IllegalArgumentException("width, height, and densityDpi must be "
   1403                         + "greater than 0");
   1404             }
   1405             if (surface != null && surface.isSingleBuffered()) {
   1406                 throw new IllegalArgumentException("Surface can't be single-buffered");
   1407             }
   1408 
   1409             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
   1410                 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
   1411             }
   1412             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
   1413                 flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
   1414             }
   1415 
   1416             if (projection != null) {
   1417                 try {
   1418                     if (!getProjectionService().isValidMediaProjection(projection)) {
   1419                         throw new SecurityException("Invalid media projection");
   1420                     }
   1421                     flags = projection.applyVirtualDisplayFlags(flags);
   1422                 } catch (RemoteException e) {
   1423                     throw new SecurityException("unable to validate media projection or flags");
   1424                 }
   1425             }
   1426 
   1427             if (callingUid != Process.SYSTEM_UID &&
   1428                     (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
   1429                 if (!canProjectVideo(projection)) {
   1430                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
   1431                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
   1432                             + "MediaProjection token in order to create a screen sharing virtual "
   1433                             + "display.");
   1434                 }
   1435             }
   1436             if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
   1437                 if (!canProjectSecureVideo(projection)) {
   1438                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
   1439                             + "or an appropriate MediaProjection token to create a "
   1440                             + "secure virtual display.");
   1441                 }
   1442             }
   1443 
   1444             final long token = Binder.clearCallingIdentity();
   1445             try {
   1446                 return createVirtualDisplayInternal(callback, projection, callingUid,
   1447                         packageName, name, width, height, densityDpi, surface, flags);
   1448             } finally {
   1449                 Binder.restoreCallingIdentity(token);
   1450             }
   1451         }
   1452 
   1453         @Override // Binder call
   1454         public void resizeVirtualDisplay(IVirtualDisplayCallback callback,
   1455                 int width, int height, int densityDpi) {
   1456             final long token = Binder.clearCallingIdentity();
   1457             try {
   1458                 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi);
   1459             } finally {
   1460                 Binder.restoreCallingIdentity(token);
   1461             }
   1462         }
   1463 
   1464         @Override // Binder call
   1465         public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) {
   1466             if (surface != null && surface.isSingleBuffered()) {
   1467                 throw new IllegalArgumentException("Surface can't be single-buffered");
   1468             }
   1469             final long token = Binder.clearCallingIdentity();
   1470             try {
   1471                 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface);
   1472             } finally {
   1473                 Binder.restoreCallingIdentity(token);
   1474             }
   1475         }
   1476 
   1477         @Override // Binder call
   1478         public void releaseVirtualDisplay(IVirtualDisplayCallback callback) {
   1479             final long token = Binder.clearCallingIdentity();
   1480             try {
   1481                 releaseVirtualDisplayInternal(callback.asBinder());
   1482             } finally {
   1483                 Binder.restoreCallingIdentity(token);
   1484             }
   1485         }
   1486 
   1487         @Override // Binder call
   1488         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   1489             if (mContext == null
   1490                     || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
   1491                             != PackageManager.PERMISSION_GRANTED) {
   1492                 pw.println("Permission Denial: can't dump DisplayManager from from pid="
   1493                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   1494                 return;
   1495             }
   1496 
   1497             final long token = Binder.clearCallingIdentity();
   1498             try {
   1499                 dumpInternal(pw);
   1500             } finally {
   1501                 Binder.restoreCallingIdentity(token);
   1502             }
   1503         }
   1504 
   1505         private boolean validatePackageName(int uid, String packageName) {
   1506             if (packageName != null) {
   1507                 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
   1508                 if (packageNames != null) {
   1509                     for (String n : packageNames) {
   1510                         if (n.equals(packageName)) {
   1511                             return true;
   1512                         }
   1513                     }
   1514                 }
   1515             }
   1516             return false;
   1517         }
   1518 
   1519         private boolean canProjectVideo(IMediaProjection projection) {
   1520             if (projection != null) {
   1521                 try {
   1522                     if (projection.canProjectVideo()) {
   1523                         return true;
   1524                     }
   1525                 } catch (RemoteException e) {
   1526                     Slog.e(TAG, "Unable to query projection service for permissions", e);
   1527                 }
   1528             }
   1529             if (mContext.checkCallingPermission(
   1530                     android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
   1531                     == PackageManager.PERMISSION_GRANTED) {
   1532                 return true;
   1533             }
   1534             return canProjectSecureVideo(projection);
   1535         }
   1536 
   1537         private boolean canProjectSecureVideo(IMediaProjection projection) {
   1538             if (projection != null) {
   1539                 try {
   1540                     if (projection.canProjectSecureVideo()){
   1541                         return true;
   1542                     }
   1543                 } catch (RemoteException e) {
   1544                     Slog.e(TAG, "Unable to query projection service for permissions", e);
   1545                 }
   1546             }
   1547             return mContext.checkCallingPermission(
   1548                     android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
   1549                     == PackageManager.PERMISSION_GRANTED;
   1550         }
   1551     }
   1552 
   1553     private final class LocalService extends DisplayManagerInternal {
   1554         @Override
   1555         public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
   1556                 SensorManager sensorManager) {
   1557             synchronized (mSyncRoot) {
   1558                 DisplayBlanker blanker = new DisplayBlanker() {
   1559                     @Override
   1560                     public void requestDisplayState(int state, int brightness) {
   1561                         // The order of operations is important for legacy reasons.
   1562                         if (state == Display.STATE_OFF) {
   1563                             requestGlobalDisplayStateInternal(state, brightness);
   1564                         }
   1565 
   1566                         callbacks.onDisplayStateChange(state);
   1567 
   1568                         if (state != Display.STATE_OFF) {
   1569                             requestGlobalDisplayStateInternal(state, brightness);
   1570                         }
   1571                     }
   1572                 };
   1573                 mDisplayPowerController = new DisplayPowerController(
   1574                         mContext, callbacks, handler, sensorManager, blanker);
   1575             }
   1576         }
   1577 
   1578         @Override
   1579         public boolean requestPowerState(DisplayPowerRequest request,
   1580                 boolean waitForNegativeProximity) {
   1581             return mDisplayPowerController.requestPowerState(request,
   1582                     waitForNegativeProximity);
   1583         }
   1584 
   1585         @Override
   1586         public boolean isProximitySensorAvailable() {
   1587             return mDisplayPowerController.isProximitySensorAvailable();
   1588         }
   1589 
   1590         @Override
   1591         public DisplayInfo getDisplayInfo(int displayId) {
   1592             return getDisplayInfoInternal(displayId, Process.myUid());
   1593         }
   1594 
   1595         @Override
   1596         public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
   1597             if (listener == null) {
   1598                 throw new IllegalArgumentException("listener must not be null");
   1599             }
   1600 
   1601             registerDisplayTransactionListenerInternal(listener);
   1602         }
   1603 
   1604         @Override
   1605         public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
   1606             if (listener == null) {
   1607                 throw new IllegalArgumentException("listener must not be null");
   1608             }
   1609 
   1610             unregisterDisplayTransactionListenerInternal(listener);
   1611         }
   1612 
   1613         @Override
   1614         public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
   1615             setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
   1616         }
   1617 
   1618         @Override
   1619         public void performTraversalInTransactionFromWindowManager() {
   1620             performTraversalInTransactionFromWindowManagerInternal();
   1621         }
   1622 
   1623         @Override
   1624         public void setDisplayProperties(int displayId, boolean hasContent,
   1625                 float requestedRefreshRate, int requestedMode, boolean inTraversal) {
   1626             setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
   1627                     requestedMode, inTraversal);
   1628         }
   1629 
   1630         @Override
   1631         public void setDisplayOffsets(int displayId, int x, int y) {
   1632             setDisplayOffsetsInternal(displayId, x, y);
   1633         }
   1634     }
   1635 }
   1636