• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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