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