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