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