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