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