1 /* 2 * Copyright (C) 2006 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 android.view; 18 19 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 20 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 21 import static android.window.WindowProviderService.isWindowProviderService; 22 23 import static com.android.window.flags.Flags.screenRecordingCallbacks; 24 25 import android.annotation.CallbackExecutor; 26 import android.annotation.IntRange; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.UiContext; 30 import android.compat.annotation.UnsupportedAppUsage; 31 import android.content.ComponentName; 32 import android.content.Context; 33 import android.graphics.Bitmap; 34 import android.graphics.Region; 35 import android.os.Bundle; 36 import android.os.IBinder; 37 import android.os.Looper; 38 import android.os.RemoteException; 39 import android.os.StrictMode; 40 import android.util.Log; 41 import android.window.ITaskFpsCallback; 42 import android.window.InputTransferToken; 43 import android.window.TaskFpsCallback; 44 import android.window.TrustedPresentationThresholds; 45 import android.window.WindowContext; 46 import android.window.WindowMetricsController; 47 import android.window.WindowProvider; 48 49 import com.android.internal.annotations.GuardedBy; 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.os.IResultReceiver; 52 53 import java.util.ArrayList; 54 import java.util.Iterator; 55 import java.util.List; 56 import java.util.Objects; 57 import java.util.Set; 58 import java.util.concurrent.Executor; 59 import java.util.function.Consumer; 60 import java.util.function.IntConsumer; 61 62 /** 63 * Provides low-level communication with the system window manager for 64 * operations that are bound to a particular context, display or parent window. 65 * Instances of this object are sensitive to the compatibility info associated 66 * with the running application. 67 * 68 * This object implements the {@link ViewManager} interface, 69 * allowing you to add any View subclass as a top-level window on the screen. 70 * Additional window manager specific layout parameters are defined for 71 * control over how windows are displayed. It also implements the {@link WindowManager} 72 * interface, allowing you to control the displays attached to the device. 73 * 74 * <p>Applications will not normally use WindowManager directly, instead relying 75 * on the higher-level facilities in {@link android.app.Activity} and 76 * {@link android.app.Dialog}. 77 * 78 * <p>Even for low-level window manager access, it is almost never correct to use 79 * this class. For example, {@link android.app.Activity#getWindowManager} 80 * provides a window manager for adding windows that are associated with that 81 * activity -- the window manager will not normally allow you to add arbitrary 82 * windows that are not associated with an activity. 83 * 84 * @see WindowManager 85 * @see WindowManagerGlobal 86 * @hide 87 */ 88 public final class WindowManagerImpl implements WindowManager { 89 private static final String TAG = "WindowManager"; 90 91 @UnsupportedAppUsage 92 private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); 93 @UiContext 94 @VisibleForTesting 95 public final Context mContext; 96 private final Window mParentWindow; 97 98 /** 99 * If {@link LayoutParams#token} is {@code null} and no parent window is specified, the value 100 * of {@link LayoutParams#token} will be overridden to {@code mDefaultToken}. 101 */ 102 private IBinder mDefaultToken; 103 104 /** 105 * This token will be set to {@link LayoutParams#mWindowContextToken} and used to receive 106 * configuration changes from the server side. 107 */ 108 @Nullable 109 private final IBinder mWindowContextToken; 110 111 @GuardedBy("mOnFpsCallbackListenerProxies") 112 private final ArrayList<OnFpsCallbackListenerProxy> mOnFpsCallbackListenerProxies = 113 new ArrayList<>(); 114 115 /** A controller to handle {@link WindowMetrics} related APIs */ 116 @NonNull 117 private final WindowMetricsController mWindowMetricsController; 118 WindowManagerImpl(Context context)119 public WindowManagerImpl(Context context) { 120 this(context, null /* parentWindow */, null /* clientToken */); 121 } 122 WindowManagerImpl(Context context, Window parentWindow, @Nullable IBinder windowContextToken)123 private WindowManagerImpl(Context context, Window parentWindow, 124 @Nullable IBinder windowContextToken) { 125 mContext = context; 126 mParentWindow = parentWindow; 127 mWindowContextToken = windowContextToken; 128 mWindowMetricsController = new WindowMetricsController(mContext); 129 } 130 createLocalWindowManager(Window parentWindow)131 public WindowManagerImpl createLocalWindowManager(Window parentWindow) { 132 return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken); 133 } 134 createPresentationWindowManager(Context displayContext)135 public WindowManagerImpl createPresentationWindowManager(Context displayContext) { 136 return new WindowManagerImpl(displayContext, mParentWindow, mWindowContextToken); 137 } 138 139 /** Creates a {@link WindowManager} for a {@link WindowContext}. */ createWindowContextWindowManager(Context context)140 public static WindowManager createWindowContextWindowManager(Context context) { 141 final IBinder clientToken = context.getWindowContextToken(); 142 return new WindowManagerImpl(context, null /* parentWindow */, clientToken); 143 } 144 145 /** 146 * Sets the window token to assign when none is specified by the client or 147 * available from the parent window. 148 * 149 * @param token The default token to assign. 150 */ setDefaultToken(IBinder token)151 public void setDefaultToken(IBinder token) { 152 mDefaultToken = token; 153 } 154 155 @Override addView(@onNull View view, @NonNull ViewGroup.LayoutParams params)156 public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { 157 applyTokens(params); 158 mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, 159 mContext.getUserId()); 160 } 161 162 @Override updateViewLayout(@onNull View view, @NonNull ViewGroup.LayoutParams params)163 public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { 164 applyTokens(params); 165 mGlobal.updateViewLayout(view, params); 166 } 167 applyTokens(@onNull ViewGroup.LayoutParams params)168 private void applyTokens(@NonNull ViewGroup.LayoutParams params) { 169 if (!(params instanceof WindowManager.LayoutParams)) { 170 throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); 171 } 172 final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; 173 assertWindowContextTypeMatches(wparams.type); 174 // Only use the default token if we don't have a parent window and a token. 175 if (mDefaultToken != null && mParentWindow == null && wparams.token == null) { 176 wparams.token = mDefaultToken; 177 } 178 wparams.mWindowContextToken = mWindowContextToken; 179 } 180 assertWindowContextTypeMatches(@ayoutParams.WindowType int windowType)181 private void assertWindowContextTypeMatches(@LayoutParams.WindowType int windowType) { 182 if (!(mContext instanceof WindowProvider)) { 183 return; 184 } 185 // Don't need to check sub-window type because sub window should be allowed to be attached 186 // to the parent window. 187 if (windowType >= FIRST_SUB_WINDOW && windowType <= LAST_SUB_WINDOW) { 188 return; 189 } 190 final WindowProvider windowProvider = (WindowProvider) mContext; 191 if (windowProvider.getWindowType() == windowType) { 192 return; 193 } 194 IllegalArgumentException exception = new IllegalArgumentException("Window type mismatch." 195 + " Window Context's window type is " + windowProvider.getWindowType() 196 + ", while LayoutParams' type is set to " + windowType + "." 197 + " Please create another Window Context via" 198 + " createWindowContext(getDisplay(), " + windowType + ", null)" 199 + " to add window with type:" + windowType); 200 if (!isWindowProviderService(windowProvider.getWindowContextOptions())) { 201 throw exception; 202 } 203 // Throw IncorrectCorrectViolation if the Window Context is allowed to provide multiple 204 // window types. Usually it's because the Window Context is a WindowProviderService. 205 StrictMode.onIncorrectContextUsed("WindowContext's window type must" 206 + " match type in WindowManager.LayoutParams", exception); 207 } 208 209 @Override removeView(View view)210 public void removeView(View view) { 211 mGlobal.removeView(view, false); 212 } 213 214 @Override removeViewImmediate(View view)215 public void removeViewImmediate(View view) { 216 mGlobal.removeView(view, true); 217 } 218 219 @Override requestAppKeyboardShortcuts( final KeyboardShortcutsReceiver receiver, int deviceId)220 public void requestAppKeyboardShortcuts( 221 final KeyboardShortcutsReceiver receiver, int deviceId) { 222 IResultReceiver resultReceiver = new IResultReceiver.Stub() { 223 @Override 224 public void send(int resultCode, Bundle resultData) throws RemoteException { 225 List<KeyboardShortcutGroup> result = 226 resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY, 227 android.view.KeyboardShortcutGroup.class); 228 receiver.onKeyboardShortcutsReceived(result); 229 } 230 }; 231 try { 232 WindowManagerGlobal.getWindowManagerService() 233 .requestAppKeyboardShortcuts(resultReceiver, deviceId); 234 } catch (RemoteException e) { 235 throw e.rethrowFromSystemServer(); 236 } 237 } 238 239 @Override requestImeKeyboardShortcuts( final KeyboardShortcutsReceiver receiver, int deviceId)240 public void requestImeKeyboardShortcuts( 241 final KeyboardShortcutsReceiver receiver, int deviceId) { 242 IResultReceiver resultReceiver = new IResultReceiver.Stub() { 243 @Override 244 public void send(int resultCode, Bundle resultData) throws RemoteException { 245 List<KeyboardShortcutGroup> result = 246 resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY, 247 android.view.KeyboardShortcutGroup.class); 248 receiver.onKeyboardShortcutsReceived(result); 249 } 250 }; 251 try { 252 WindowManagerGlobal.getWindowManagerService() 253 .requestImeKeyboardShortcuts(resultReceiver, deviceId); 254 } catch (RemoteException e) { 255 throw e.rethrowFromSystemServer(); 256 } 257 } 258 259 @Override getDefaultDisplay()260 public Display getDefaultDisplay() { 261 return mContext.getDisplayNoVerify(); 262 } 263 264 @Override getCurrentImeTouchRegion()265 public Region getCurrentImeTouchRegion() { 266 try { 267 return WindowManagerGlobal.getWindowManagerService().getCurrentImeTouchRegion(); 268 } catch (RemoteException e) { 269 } 270 return null; 271 } 272 273 @Override setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow)274 public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) { 275 try { 276 WindowManagerGlobal.getWindowManagerService() 277 .setShouldShowWithInsecureKeyguard(displayId, shouldShow); 278 } catch (RemoteException e) { 279 } 280 } 281 282 @Override setShouldShowSystemDecors(int displayId, boolean shouldShow)283 public void setShouldShowSystemDecors(int displayId, boolean shouldShow) { 284 try { 285 WindowManagerGlobal.getWindowManagerService() 286 .setShouldShowSystemDecors(displayId, shouldShow); 287 } catch (RemoteException e) { 288 } 289 } 290 291 @Override shouldShowSystemDecors(int displayId)292 public boolean shouldShowSystemDecors(int displayId) { 293 try { 294 return WindowManagerGlobal.getWindowManagerService().shouldShowSystemDecors(displayId); 295 } catch (RemoteException e) { 296 } 297 return false; 298 } 299 300 @Override setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy)301 public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { 302 try { 303 WindowManagerGlobal.getWindowManagerService().setDisplayImePolicy(displayId, imePolicy); 304 } catch (RemoteException e) { 305 } 306 } 307 308 @Override getDisplayImePolicy(int displayId)309 public @DisplayImePolicy int getDisplayImePolicy(int displayId) { 310 try { 311 return WindowManagerGlobal.getWindowManagerService().getDisplayImePolicy(displayId); 312 } catch (RemoteException e) { 313 } 314 return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 315 } 316 317 @Override isGlobalKey(int keyCode)318 public boolean isGlobalKey(int keyCode) { 319 try { 320 return WindowManagerGlobal.getWindowManagerService().isGlobalKey(keyCode); 321 } catch (RemoteException e) { 322 } 323 return false; 324 } 325 326 @Override getCurrentWindowMetrics()327 public WindowMetrics getCurrentWindowMetrics() { 328 return mWindowMetricsController.getCurrentWindowMetrics(); 329 } 330 331 @Override getMaximumWindowMetrics()332 public WindowMetrics getMaximumWindowMetrics() { 333 return mWindowMetricsController.getMaximumWindowMetrics(); 334 } 335 336 @Override 337 @NonNull getPossibleMaximumWindowMetrics(int displayId)338 public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) { 339 return mWindowMetricsController.getPossibleMaximumWindowMetrics(displayId); 340 } 341 342 @Override holdLock(IBinder token, int durationMs)343 public void holdLock(IBinder token, int durationMs) { 344 try { 345 WindowManagerGlobal.getWindowManagerService().holdLock(token, durationMs); 346 } catch (RemoteException e) { 347 throw e.rethrowFromSystemServer(); 348 } 349 } 350 351 @Override isCrossWindowBlurEnabled()352 public boolean isCrossWindowBlurEnabled() { 353 return CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled(); 354 } 355 356 @Override addCrossWindowBlurEnabledListener(@onNull Consumer<Boolean> listener)357 public void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) { 358 addCrossWindowBlurEnabledListener(mContext.getMainExecutor(), listener); 359 } 360 361 @Override addCrossWindowBlurEnabledListener(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> listener)362 public void addCrossWindowBlurEnabledListener(@NonNull @CallbackExecutor Executor executor, 363 @NonNull Consumer<Boolean> listener) { 364 CrossWindowBlurListeners.getInstance().addListener(executor, listener); 365 } 366 367 @Override removeCrossWindowBlurEnabledListener(@onNull Consumer<Boolean> listener)368 public void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) { 369 CrossWindowBlurListeners.getInstance().removeListener(listener); 370 } 371 372 @Override addProposedRotationListener(@onNull @allbackExecutor Executor executor, @NonNull IntConsumer listener)373 public void addProposedRotationListener(@NonNull @CallbackExecutor Executor executor, 374 @NonNull IntConsumer listener) { 375 Objects.requireNonNull(executor, "executor must not be null"); 376 Objects.requireNonNull(listener, "listener must not be null"); 377 final IBinder contextToken = Context.getToken(mContext); 378 if (contextToken == null) { 379 throw new UnsupportedOperationException("The context of this window manager instance " 380 + "must be a UI context, e.g. an Activity or a Context created by " 381 + "Context#createWindowContext()"); 382 } 383 mGlobal.registerProposedRotationListener(contextToken, executor, listener); 384 } 385 386 @Override removeProposedRotationListener(@onNull IntConsumer listener)387 public void removeProposedRotationListener(@NonNull IntConsumer listener) { 388 mGlobal.unregisterProposedRotationListener(Context.getToken(mContext), listener); 389 } 390 391 @Override isTaskSnapshotSupported()392 public boolean isTaskSnapshotSupported() { 393 try { 394 return WindowManagerGlobal.getWindowManagerService().isTaskSnapshotSupported(); 395 } catch (RemoteException e) { 396 } 397 return false; 398 } 399 400 @Override registerTaskFpsCallback(@ntRangefrom = 0) int taskId, @NonNull Executor executor, TaskFpsCallback callback)401 public void registerTaskFpsCallback(@IntRange(from = 0) int taskId, @NonNull Executor executor, 402 TaskFpsCallback callback) { 403 final OnFpsCallbackListenerProxy onFpsCallbackListenerProxy = 404 new OnFpsCallbackListenerProxy(executor, callback); 405 try { 406 WindowManagerGlobal.getWindowManagerService().registerTaskFpsCallback( 407 taskId, onFpsCallbackListenerProxy); 408 } catch (RemoteException e) { 409 throw e.rethrowFromSystemServer(); 410 } 411 synchronized (mOnFpsCallbackListenerProxies) { 412 mOnFpsCallbackListenerProxies.add(onFpsCallbackListenerProxy); 413 } 414 } 415 416 @Override unregisterTaskFpsCallback(TaskFpsCallback callback)417 public void unregisterTaskFpsCallback(TaskFpsCallback callback) { 418 synchronized (mOnFpsCallbackListenerProxies) { 419 final Iterator<OnFpsCallbackListenerProxy> iterator = 420 mOnFpsCallbackListenerProxies.iterator(); 421 while (iterator.hasNext()) { 422 final OnFpsCallbackListenerProxy proxy = iterator.next(); 423 if (proxy.mCallback == callback) { 424 try { 425 WindowManagerGlobal.getWindowManagerService() 426 .unregisterTaskFpsCallback(proxy); 427 } catch (RemoteException e) { 428 throw e.rethrowFromSystemServer(); 429 } 430 iterator.remove(); 431 } 432 } 433 } 434 } 435 436 private static class OnFpsCallbackListenerProxy 437 extends ITaskFpsCallback.Stub { 438 private final Executor mExecutor; 439 private final TaskFpsCallback mCallback; 440 OnFpsCallbackListenerProxy(Executor executor, TaskFpsCallback callback)441 private OnFpsCallbackListenerProxy(Executor executor, TaskFpsCallback callback) { 442 mExecutor = executor; 443 mCallback = callback; 444 } 445 446 @Override onFpsReported(float fps)447 public void onFpsReported(float fps) { 448 mExecutor.execute(() -> { 449 mCallback.onFpsReported(fps); 450 }); 451 } 452 } 453 454 @Override snapshotTaskForRecents(int taskId)455 public Bitmap snapshotTaskForRecents(int taskId) { 456 try { 457 return WindowManagerGlobal.getWindowManagerService().snapshotTaskForRecents(taskId); 458 } catch (RemoteException e) { 459 e.rethrowAsRuntimeException(); 460 } 461 return null; 462 } 463 464 @Override 465 @NonNull getDefaultToken()466 public IBinder getDefaultToken() { 467 return mDefaultToken; 468 } 469 470 @Override 471 @NonNull notifyScreenshotListeners(int displayId)472 public List<ComponentName> notifyScreenshotListeners(int displayId) { 473 try { 474 return List.copyOf(WindowManagerGlobal.getWindowManagerService() 475 .notifyScreenshotListeners(displayId)); 476 } catch (RemoteException e) { 477 throw e.rethrowFromSystemServer(); 478 } 479 } 480 481 @Override replaceContentOnDisplayWithMirror(int displayId, @NonNull Window window)482 public boolean replaceContentOnDisplayWithMirror(int displayId, @NonNull Window window) { 483 View decorView = window.peekDecorView(); 484 if (decorView == null) { 485 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's decorView was null."); 486 return false; 487 } 488 489 ViewRootImpl viewRoot = decorView.getViewRootImpl(); 490 if (viewRoot == null) { 491 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's viewRootImpl was null."); 492 return false; 493 } 494 495 SurfaceControl sc = viewRoot.getSurfaceControl(); 496 if (!sc.isValid()) { 497 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's SC is invalid."); 498 return false; 499 } 500 return replaceContentOnDisplayWithSc(displayId, SurfaceControl.mirrorSurface(sc)); 501 } 502 503 @Override replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc)504 public boolean replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc) { 505 if (!sc.isValid()) { 506 Log.e(TAG, "replaceContentOnDisplayWithSc: Invalid SC."); 507 return false; 508 } 509 510 try { 511 return WindowManagerGlobal.getWindowManagerService() 512 .replaceContentOnDisplay(displayId, sc); 513 } catch (RemoteException e) { 514 e.rethrowAsRuntimeException(); 515 } 516 return false; 517 } 518 519 @Override registerTrustedPresentationListener(@onNull IBinder window, @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor, @NonNull Consumer<Boolean> listener)520 public void registerTrustedPresentationListener(@NonNull IBinder window, 521 @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor, 522 @NonNull Consumer<Boolean> listener) { 523 Objects.requireNonNull(window, "window must not be null"); 524 Objects.requireNonNull(thresholds, "thresholds must not be null"); 525 Objects.requireNonNull(executor, "executor must not be null"); 526 Objects.requireNonNull(listener, "listener must not be null"); 527 mGlobal.registerTrustedPresentationListener(window, thresholds, executor, listener); 528 } 529 530 @Override unregisterTrustedPresentationListener(@onNull Consumer<Boolean> listener)531 public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) { 532 Objects.requireNonNull(listener, "listener must not be null"); 533 mGlobal.unregisterTrustedPresentationListener(listener); 534 } 535 536 @NonNull 537 @Override registerBatchedSurfaceControlInputReceiver( @onNull InputTransferToken hostInputTransferToken, @NonNull SurfaceControl surfaceControl, @NonNull Choreographer choreographer, @NonNull SurfaceControlInputReceiver receiver)538 public InputTransferToken registerBatchedSurfaceControlInputReceiver( 539 @NonNull InputTransferToken hostInputTransferToken, 540 @NonNull SurfaceControl surfaceControl, @NonNull Choreographer choreographer, 541 @NonNull SurfaceControlInputReceiver receiver) { 542 Objects.requireNonNull(hostInputTransferToken); 543 Objects.requireNonNull(surfaceControl); 544 Objects.requireNonNull(choreographer); 545 Objects.requireNonNull(receiver); 546 return mGlobal.registerBatchedSurfaceControlInputReceiver(hostInputTransferToken, 547 surfaceControl, choreographer, receiver); 548 } 549 550 @NonNull 551 @Override registerUnbatchedSurfaceControlInputReceiver( @onNull InputTransferToken hostInputTransferToken, @NonNull SurfaceControl surfaceControl, @NonNull Looper looper, @NonNull SurfaceControlInputReceiver receiver)552 public InputTransferToken registerUnbatchedSurfaceControlInputReceiver( 553 @NonNull InputTransferToken hostInputTransferToken, 554 @NonNull SurfaceControl surfaceControl, @NonNull Looper looper, 555 @NonNull SurfaceControlInputReceiver receiver) { 556 Objects.requireNonNull(hostInputTransferToken); 557 Objects.requireNonNull(surfaceControl); 558 Objects.requireNonNull(looper); 559 Objects.requireNonNull(receiver); 560 return mGlobal.registerUnbatchedSurfaceControlInputReceiver( 561 hostInputTransferToken, surfaceControl, looper, receiver); 562 } 563 564 @Override unregisterSurfaceControlInputReceiver(@onNull SurfaceControl surfaceControl)565 public void unregisterSurfaceControlInputReceiver(@NonNull SurfaceControl surfaceControl) { 566 Objects.requireNonNull(surfaceControl); 567 mGlobal.unregisterSurfaceControlInputReceiver(surfaceControl); 568 } 569 570 @Override 571 @Nullable getSurfaceControlInputClientToken(@onNull SurfaceControl surfaceControl)572 public IBinder getSurfaceControlInputClientToken(@NonNull SurfaceControl surfaceControl) { 573 Objects.requireNonNull(surfaceControl); 574 return mGlobal.getSurfaceControlInputClientToken(surfaceControl); 575 } 576 577 @Override transferTouchGesture(@onNull InputTransferToken transferFromToken, @NonNull InputTransferToken transferToToken)578 public boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken, 579 @NonNull InputTransferToken transferToToken) { 580 Objects.requireNonNull(transferFromToken); 581 Objects.requireNonNull(transferToToken); 582 return mGlobal.transferTouchGesture(transferFromToken, transferToToken); 583 } 584 585 @Override addScreenRecordingCallback( @onNull @allbackExecutor Executor executor, @NonNull Consumer<@ScreenRecordingState Integer> callback)586 public @ScreenRecordingState int addScreenRecordingCallback( 587 @NonNull @CallbackExecutor Executor executor, 588 @NonNull Consumer<@ScreenRecordingState Integer> callback) { 589 if (screenRecordingCallbacks()) { 590 Objects.requireNonNull(executor, "executor must not be null"); 591 Objects.requireNonNull(callback, "callback must not be null"); 592 return ScreenRecordingCallbacks.getInstance().addCallback(executor, callback); 593 } 594 return SCREEN_RECORDING_STATE_NOT_VISIBLE; 595 } 596 597 @Override removeScreenRecordingCallback( @onNull Consumer<@ScreenRecordingState Integer> callback)598 public void removeScreenRecordingCallback( 599 @NonNull Consumer<@ScreenRecordingState Integer> callback) { 600 if (screenRecordingCallbacks()) { 601 Objects.requireNonNull(callback, "callback must not be null"); 602 ScreenRecordingCallbacks.getInstance().removeCallback(callback); 603 } 604 } 605 } 606