• 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 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