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 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 public 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 getApplicationLaunchKeyboardShortcuts(int deviceId)240 public KeyboardShortcutGroup getApplicationLaunchKeyboardShortcuts(int deviceId) { 241 try { 242 return WindowManagerGlobal.getWindowManagerService() 243 .getApplicationLaunchKeyboardShortcuts(deviceId); 244 } catch (RemoteException e) { 245 throw e.rethrowFromSystemServer(); 246 } 247 } 248 249 @Override requestImeKeyboardShortcuts( final KeyboardShortcutsReceiver receiver, int deviceId)250 public void requestImeKeyboardShortcuts( 251 final KeyboardShortcutsReceiver receiver, int deviceId) { 252 IResultReceiver resultReceiver = new IResultReceiver.Stub() { 253 @Override 254 public void send(int resultCode, Bundle resultData) throws RemoteException { 255 List<KeyboardShortcutGroup> result = 256 resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY, 257 android.view.KeyboardShortcutGroup.class); 258 receiver.onKeyboardShortcutsReceived(result); 259 } 260 }; 261 try { 262 WindowManagerGlobal.getWindowManagerService() 263 .requestImeKeyboardShortcuts(resultReceiver, deviceId); 264 } catch (RemoteException e) { 265 throw e.rethrowFromSystemServer(); 266 } 267 } 268 269 @Override getDefaultDisplay()270 public Display getDefaultDisplay() { 271 return mContext.getDisplayNoVerify(); 272 } 273 274 @Override getCurrentImeTouchRegion()275 public Region getCurrentImeTouchRegion() { 276 try { 277 return WindowManagerGlobal.getWindowManagerService().getCurrentImeTouchRegion(); 278 } catch (RemoteException e) { 279 } 280 return null; 281 } 282 283 @Override setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow)284 public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) { 285 try { 286 WindowManagerGlobal.getWindowManagerService() 287 .setShouldShowWithInsecureKeyguard(displayId, shouldShow); 288 } catch (RemoteException e) { 289 } 290 } 291 292 @Override setShouldShowSystemDecors(int displayId, boolean shouldShow)293 public void setShouldShowSystemDecors(int displayId, boolean shouldShow) { 294 try { 295 WindowManagerGlobal.getWindowManagerService() 296 .setShouldShowSystemDecors(displayId, shouldShow); 297 } catch (RemoteException e) { 298 } 299 } 300 301 @Override shouldShowSystemDecors(int displayId)302 public boolean shouldShowSystemDecors(int displayId) { 303 try { 304 return WindowManagerGlobal.getWindowManagerService().shouldShowSystemDecors(displayId); 305 } catch (RemoteException e) { 306 } 307 return false; 308 } 309 310 @Override setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy)311 public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { 312 try { 313 WindowManagerGlobal.getWindowManagerService().setDisplayImePolicy(displayId, imePolicy); 314 } catch (RemoteException e) { 315 } 316 } 317 318 @Override getDisplayImePolicy(int displayId)319 public @DisplayImePolicy int getDisplayImePolicy(int displayId) { 320 try { 321 return WindowManagerGlobal.getWindowManagerService().getDisplayImePolicy(displayId); 322 } catch (RemoteException e) { 323 } 324 return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; 325 } 326 327 @Override isGlobalKey(int keyCode)328 public boolean isGlobalKey(int keyCode) { 329 try { 330 return WindowManagerGlobal.getWindowManagerService().isGlobalKey(keyCode); 331 } catch (RemoteException e) { 332 } 333 return false; 334 } 335 336 @Override getCurrentWindowMetrics()337 public WindowMetrics getCurrentWindowMetrics() { 338 return mWindowMetricsController.getCurrentWindowMetrics(); 339 } 340 341 @Override getMaximumWindowMetrics()342 public WindowMetrics getMaximumWindowMetrics() { 343 return mWindowMetricsController.getMaximumWindowMetrics(); 344 } 345 346 @Override 347 @NonNull getPossibleMaximumWindowMetrics(int displayId)348 public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) { 349 return mWindowMetricsController.getPossibleMaximumWindowMetrics(displayId); 350 } 351 352 @Override holdLock(IBinder token, int durationMs)353 public void holdLock(IBinder token, int durationMs) { 354 try { 355 WindowManagerGlobal.getWindowManagerService().holdLock(token, durationMs); 356 } catch (RemoteException e) { 357 throw e.rethrowFromSystemServer(); 358 } 359 } 360 361 @Override isCrossWindowBlurEnabled()362 public boolean isCrossWindowBlurEnabled() { 363 return CrossWindowBlurListeners.getInstance().isCrossWindowBlurEnabled(); 364 } 365 366 @Override addCrossWindowBlurEnabledListener(@onNull Consumer<Boolean> listener)367 public void addCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) { 368 addCrossWindowBlurEnabledListener(mContext.getMainExecutor(), listener); 369 } 370 371 @Override addCrossWindowBlurEnabledListener(@onNull @allbackExecutor Executor executor, @NonNull Consumer<Boolean> listener)372 public void addCrossWindowBlurEnabledListener(@NonNull @CallbackExecutor Executor executor, 373 @NonNull Consumer<Boolean> listener) { 374 CrossWindowBlurListeners.getInstance().addListener(executor, listener); 375 } 376 377 @Override removeCrossWindowBlurEnabledListener(@onNull Consumer<Boolean> listener)378 public void removeCrossWindowBlurEnabledListener(@NonNull Consumer<Boolean> listener) { 379 CrossWindowBlurListeners.getInstance().removeListener(listener); 380 } 381 382 @Override addProposedRotationListener(@onNull @allbackExecutor Executor executor, @NonNull IntConsumer listener)383 public void addProposedRotationListener(@NonNull @CallbackExecutor Executor executor, 384 @NonNull IntConsumer listener) { 385 Objects.requireNonNull(executor, "executor must not be null"); 386 Objects.requireNonNull(listener, "listener must not be null"); 387 final IBinder contextToken = Context.getToken(mContext); 388 if (contextToken == null) { 389 throw new UnsupportedOperationException("The context of this window manager instance " 390 + "must be a UI context, e.g. an Activity or a Context created by " 391 + "Context#createWindowContext()"); 392 } 393 mGlobal.registerProposedRotationListener(contextToken, executor, listener); 394 } 395 396 @Override removeProposedRotationListener(@onNull IntConsumer listener)397 public void removeProposedRotationListener(@NonNull IntConsumer listener) { 398 mGlobal.unregisterProposedRotationListener(Context.getToken(mContext), listener); 399 } 400 401 @Override isTaskSnapshotSupported()402 public boolean isTaskSnapshotSupported() { 403 try { 404 return WindowManagerGlobal.getWindowManagerService().isTaskSnapshotSupported(); 405 } catch (RemoteException e) { 406 } 407 return false; 408 } 409 410 @Override registerTaskFpsCallback(@ntRangefrom = 0) int taskId, @NonNull Executor executor, TaskFpsCallback callback)411 public void registerTaskFpsCallback(@IntRange(from = 0) int taskId, @NonNull Executor executor, 412 TaskFpsCallback callback) { 413 final OnFpsCallbackListenerProxy onFpsCallbackListenerProxy = 414 new OnFpsCallbackListenerProxy(executor, callback); 415 try { 416 WindowManagerGlobal.getWindowManagerService().registerTaskFpsCallback( 417 taskId, onFpsCallbackListenerProxy); 418 } catch (RemoteException e) { 419 throw e.rethrowFromSystemServer(); 420 } 421 synchronized (mOnFpsCallbackListenerProxies) { 422 mOnFpsCallbackListenerProxies.add(onFpsCallbackListenerProxy); 423 } 424 } 425 426 @Override unregisterTaskFpsCallback(TaskFpsCallback callback)427 public void unregisterTaskFpsCallback(TaskFpsCallback callback) { 428 synchronized (mOnFpsCallbackListenerProxies) { 429 final Iterator<OnFpsCallbackListenerProxy> iterator = 430 mOnFpsCallbackListenerProxies.iterator(); 431 while (iterator.hasNext()) { 432 final OnFpsCallbackListenerProxy proxy = iterator.next(); 433 if (proxy.mCallback == callback) { 434 try { 435 WindowManagerGlobal.getWindowManagerService() 436 .unregisterTaskFpsCallback(proxy); 437 } catch (RemoteException e) { 438 throw e.rethrowFromSystemServer(); 439 } 440 iterator.remove(); 441 } 442 } 443 } 444 } 445 446 private static class OnFpsCallbackListenerProxy 447 extends ITaskFpsCallback.Stub { 448 private final Executor mExecutor; 449 private final TaskFpsCallback mCallback; 450 OnFpsCallbackListenerProxy(Executor executor, TaskFpsCallback callback)451 private OnFpsCallbackListenerProxy(Executor executor, TaskFpsCallback callback) { 452 mExecutor = executor; 453 mCallback = callback; 454 } 455 456 @Override onFpsReported(float fps)457 public void onFpsReported(float fps) { 458 mExecutor.execute(() -> { 459 mCallback.onFpsReported(fps); 460 }); 461 } 462 } 463 464 @Override snapshotTaskForRecents(int taskId)465 public Bitmap snapshotTaskForRecents(int taskId) { 466 try { 467 return WindowManagerGlobal.getWindowManagerService().snapshotTaskForRecents(taskId); 468 } catch (RemoteException e) { 469 e.rethrowAsRuntimeException(); 470 } 471 return null; 472 } 473 474 @Override 475 @NonNull getDefaultToken()476 public IBinder getDefaultToken() { 477 return mDefaultToken; 478 } 479 480 @Override 481 @NonNull notifyScreenshotListeners(int displayId)482 public List<ComponentName> notifyScreenshotListeners(int displayId) { 483 try { 484 return List.copyOf(WindowManagerGlobal.getWindowManagerService() 485 .notifyScreenshotListeners(displayId)); 486 } catch (RemoteException e) { 487 throw e.rethrowFromSystemServer(); 488 } 489 } 490 491 @Override replaceContentOnDisplayWithMirror(int displayId, @NonNull Window window)492 public boolean replaceContentOnDisplayWithMirror(int displayId, @NonNull Window window) { 493 View decorView = window.peekDecorView(); 494 if (decorView == null) { 495 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's decorView was null."); 496 return false; 497 } 498 499 ViewRootImpl viewRoot = decorView.getViewRootImpl(); 500 if (viewRoot == null) { 501 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's viewRootImpl was null."); 502 return false; 503 } 504 505 SurfaceControl sc = viewRoot.getSurfaceControl(); 506 if (!sc.isValid()) { 507 Log.e(TAG, "replaceContentOnDisplayWithMirror: Window's SC is invalid."); 508 return false; 509 } 510 return replaceContentOnDisplayWithSc(displayId, SurfaceControl.mirrorSurface(sc)); 511 } 512 513 @Override replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc)514 public boolean replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc) { 515 if (!sc.isValid()) { 516 Log.e(TAG, "replaceContentOnDisplayWithSc: Invalid SC."); 517 return false; 518 } 519 520 try { 521 return WindowManagerGlobal.getWindowManagerService() 522 .replaceContentOnDisplay(displayId, sc); 523 } catch (RemoteException e) { 524 e.rethrowAsRuntimeException(); 525 } 526 return false; 527 } 528 529 @Override registerTrustedPresentationListener(@onNull IBinder window, @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor, @NonNull Consumer<Boolean> listener)530 public void registerTrustedPresentationListener(@NonNull IBinder window, 531 @NonNull TrustedPresentationThresholds thresholds, @NonNull Executor executor, 532 @NonNull Consumer<Boolean> listener) { 533 Objects.requireNonNull(window, "window must not be null"); 534 Objects.requireNonNull(thresholds, "thresholds must not be null"); 535 Objects.requireNonNull(executor, "executor must not be null"); 536 Objects.requireNonNull(listener, "listener must not be null"); 537 mGlobal.registerTrustedPresentationListener(window, thresholds, executor, listener); 538 } 539 540 @Override unregisterTrustedPresentationListener(@onNull Consumer<Boolean> listener)541 public void unregisterTrustedPresentationListener(@NonNull Consumer<Boolean> listener) { 542 Objects.requireNonNull(listener, "listener must not be null"); 543 mGlobal.unregisterTrustedPresentationListener(listener); 544 } 545 546 @NonNull 547 @Override registerBatchedSurfaceControlInputReceiver( @onNull InputTransferToken hostInputTransferToken, @NonNull SurfaceControl surfaceControl, @NonNull Choreographer choreographer, @NonNull SurfaceControlInputReceiver receiver)548 public InputTransferToken registerBatchedSurfaceControlInputReceiver( 549 @NonNull InputTransferToken hostInputTransferToken, 550 @NonNull SurfaceControl surfaceControl, @NonNull Choreographer choreographer, 551 @NonNull SurfaceControlInputReceiver receiver) { 552 Objects.requireNonNull(hostInputTransferToken); 553 Objects.requireNonNull(surfaceControl); 554 Objects.requireNonNull(choreographer); 555 Objects.requireNonNull(receiver); 556 return mGlobal.registerBatchedSurfaceControlInputReceiver(hostInputTransferToken, 557 surfaceControl, choreographer, receiver); 558 } 559 560 @NonNull 561 @Override registerUnbatchedSurfaceControlInputReceiver( @onNull InputTransferToken hostInputTransferToken, @NonNull SurfaceControl surfaceControl, @NonNull Looper looper, @NonNull SurfaceControlInputReceiver receiver)562 public InputTransferToken registerUnbatchedSurfaceControlInputReceiver( 563 @NonNull InputTransferToken hostInputTransferToken, 564 @NonNull SurfaceControl surfaceControl, @NonNull Looper looper, 565 @NonNull SurfaceControlInputReceiver receiver) { 566 Objects.requireNonNull(hostInputTransferToken); 567 Objects.requireNonNull(surfaceControl); 568 Objects.requireNonNull(looper); 569 Objects.requireNonNull(receiver); 570 return mGlobal.registerUnbatchedSurfaceControlInputReceiver( 571 hostInputTransferToken, surfaceControl, looper, receiver); 572 } 573 574 @Override unregisterSurfaceControlInputReceiver(@onNull SurfaceControl surfaceControl)575 public void unregisterSurfaceControlInputReceiver(@NonNull SurfaceControl surfaceControl) { 576 Objects.requireNonNull(surfaceControl); 577 mGlobal.unregisterSurfaceControlInputReceiver(surfaceControl); 578 } 579 580 @Override 581 @Nullable getSurfaceControlInputClientToken(@onNull SurfaceControl surfaceControl)582 public IBinder getSurfaceControlInputClientToken(@NonNull SurfaceControl surfaceControl) { 583 Objects.requireNonNull(surfaceControl); 584 return mGlobal.getSurfaceControlInputClientToken(surfaceControl); 585 } 586 587 @Override transferTouchGesture(@onNull InputTransferToken transferFromToken, @NonNull InputTransferToken transferToToken)588 public boolean transferTouchGesture(@NonNull InputTransferToken transferFromToken, 589 @NonNull InputTransferToken transferToToken) { 590 Objects.requireNonNull(transferFromToken); 591 Objects.requireNonNull(transferToToken); 592 return mGlobal.transferTouchGesture(transferFromToken, transferToToken); 593 } 594 595 @Override addScreenRecordingCallback( @onNull @allbackExecutor Executor executor, @NonNull Consumer<@ScreenRecordingState Integer> callback)596 public @ScreenRecordingState int addScreenRecordingCallback( 597 @NonNull @CallbackExecutor Executor executor, 598 @NonNull Consumer<@ScreenRecordingState Integer> callback) { 599 if (screenRecordingCallbacks()) { 600 Objects.requireNonNull(executor, "executor must not be null"); 601 Objects.requireNonNull(callback, "callback must not be null"); 602 return ScreenRecordingCallbacks.getInstance().addCallback(executor, callback); 603 } 604 return SCREEN_RECORDING_STATE_NOT_VISIBLE; 605 } 606 607 @Override removeScreenRecordingCallback( @onNull Consumer<@ScreenRecordingState Integer> callback)608 public void removeScreenRecordingCallback( 609 @NonNull Consumer<@ScreenRecordingState Integer> callback) { 610 if (screenRecordingCallbacks()) { 611 Objects.requireNonNull(callback, "callback must not be null"); 612 ScreenRecordingCallbacks.getInstance().removeCallback(callback); 613 } 614 } 615 } 616