• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.input;
18 
19 import static android.provider.DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT;
20 import static android.view.KeyEvent.KEYCODE_UNKNOWN;
21 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
22 
23 import android.Manifest;
24 import android.annotation.EnforcePermission;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.UserIdInt;
28 import android.app.ActivityManagerInternal;
29 import android.bluetooth.BluetoothAdapter;
30 import android.bluetooth.BluetoothDevice;
31 import android.content.BroadcastReceiver;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.content.pm.PackageManager;
36 import android.graphics.PixelFormat;
37 import android.graphics.PointF;
38 import android.hardware.SensorPrivacyManager;
39 import android.hardware.SensorPrivacyManager.Sensors;
40 import android.hardware.SensorPrivacyManagerInternal;
41 import android.hardware.display.DisplayManagerInternal;
42 import android.hardware.display.DisplayViewport;
43 import android.hardware.input.HostUsiVersion;
44 import android.hardware.input.IInputDeviceBatteryListener;
45 import android.hardware.input.IInputDeviceBatteryState;
46 import android.hardware.input.IInputDevicesChangedListener;
47 import android.hardware.input.IInputManager;
48 import android.hardware.input.IInputSensorEventListener;
49 import android.hardware.input.IKeyboardBacklightListener;
50 import android.hardware.input.IStickyModifierStateListener;
51 import android.hardware.input.ITabletModeChangedListener;
52 import android.hardware.input.InputDeviceIdentifier;
53 import android.hardware.input.InputManager;
54 import android.hardware.input.InputSensorInfo;
55 import android.hardware.input.InputSettings;
56 import android.hardware.input.KeyboardLayout;
57 import android.hardware.input.KeyboardLayoutSelectionResult;
58 import android.hardware.input.TouchCalibration;
59 import android.hardware.lights.Light;
60 import android.hardware.lights.LightState;
61 import android.media.AudioManager;
62 import android.os.Binder;
63 import android.os.CombinedVibration;
64 import android.os.Environment;
65 import android.os.Handler;
66 import android.os.IBinder;
67 import android.os.IVibratorStateListener;
68 import android.os.InputEventInjectionResult;
69 import android.os.InputEventInjectionSync;
70 import android.os.Looper;
71 import android.os.Message;
72 import android.os.Process;
73 import android.os.RemoteCallbackList;
74 import android.os.RemoteException;
75 import android.os.ResultReceiver;
76 import android.os.ShellCallback;
77 import android.os.UserHandle;
78 import android.os.VibrationEffect;
79 import android.os.vibrator.StepSegment;
80 import android.os.vibrator.VibrationEffectSegment;
81 import android.provider.DeviceConfig;
82 import android.text.TextUtils;
83 import android.util.ArrayMap;
84 import android.util.IndentingPrintWriter;
85 import android.util.Log;
86 import android.util.Slog;
87 import android.util.SparseArray;
88 import android.util.SparseBooleanArray;
89 import android.view.Display;
90 import android.view.IInputFilter;
91 import android.view.IInputFilterHost;
92 import android.view.IInputMonitorHost;
93 import android.view.InputApplicationHandle;
94 import android.view.InputChannel;
95 import android.view.InputDevice;
96 import android.view.InputEvent;
97 import android.view.InputMonitor;
98 import android.view.KeyCharacterMap;
99 import android.view.KeyEvent;
100 import android.view.PointerIcon;
101 import android.view.Surface;
102 import android.view.SurfaceControl;
103 import android.view.VerifiedInputEvent;
104 import android.view.ViewConfiguration;
105 import android.view.WindowManager;
106 import android.view.inputmethod.InputMethodInfo;
107 import android.view.inputmethod.InputMethodSubtype;
108 
109 import com.android.internal.R;
110 import com.android.internal.annotations.GuardedBy;
111 import com.android.internal.annotations.VisibleForTesting;
112 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
113 import com.android.internal.os.SomeArgs;
114 import com.android.internal.util.DumpUtils;
115 import com.android.internal.util.Preconditions;
116 import com.android.server.DisplayThread;
117 import com.android.server.LocalServices;
118 import com.android.server.Watchdog;
119 import com.android.server.input.InputManagerInternal.LidSwitchCallback;
120 import com.android.server.input.debug.FocusEventDebugView;
121 import com.android.server.inputmethod.InputMethodManagerInternal;
122 import com.android.server.policy.WindowManagerPolicy;
123 
124 import libcore.io.IoUtils;
125 
126 import java.io.File;
127 import java.io.FileDescriptor;
128 import java.io.FileInputStream;
129 import java.io.FileNotFoundException;
130 import java.io.FileWriter;
131 import java.io.IOException;
132 import java.io.InputStream;
133 import java.io.PrintWriter;
134 import java.util.ArrayList;
135 import java.util.Arrays;
136 import java.util.HashMap;
137 import java.util.List;
138 import java.util.Map;
139 import java.util.Objects;
140 import java.util.OptionalInt;
141 import java.util.function.Consumer;
142 
143 /** The system implementation of {@link IInputManager} that manages input devices. */
144 public class InputManagerService extends IInputManager.Stub
145         implements Watchdog.Monitor {
146     static final String TAG = "InputManager";
147     // To enable these logs, run: 'adb shell setprop log.tag.InputManager DEBUG' (requires restart)
148     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
149 
150     private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
151     private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml";
152 
153     // Feature flag name for the strategy to be used in VelocityTracker
154     private static final String VELOCITYTRACKER_STRATEGY_PROPERTY = "velocitytracker_strategy";
155 
156     private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
157     private static final int MSG_RELOAD_DEVICE_ALIASES = 2;
158     private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 3;
159 
160     private static final int DEFAULT_VIBRATION_MAGNITUDE = 192;
161     private static final AdditionalDisplayInputProperties
162             DEFAULT_ADDITIONAL_DISPLAY_INPUT_PROPERTIES = new AdditionalDisplayInputProperties();
163 
164     private final NativeInputManagerService mNative;
165 
166     private final Context mContext;
167     private final InputManagerHandler mHandler;
168     private DisplayManagerInternal mDisplayManagerInternal;
169 
170     private InputMethodManagerInternal mInputMethodManagerInternal;
171 
172     private final File mDoubleTouchGestureEnableFile;
173 
174     private WindowManagerCallbacks mWindowManagerCallbacks;
175     private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
176     private boolean mSystemReady;
177 
178     private final Object mTabletModeLock = new Object();
179     // List of currently registered tablet mode changed listeners by process id
180     @GuardedBy("mTabletModeLock")
181     private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners =
182             new SparseArray<>();
183     private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
184             new ArrayList<>();
185 
186     private final Object mSensorEventLock = new Object();
187     // List of currently registered sensor event listeners by process id
188     @GuardedBy("mSensorEventLock")
189     private final SparseArray<SensorEventListenerRecord> mSensorEventListeners =
190             new SparseArray<>();
191     private final List<SensorEventListenerRecord> mSensorEventListenersToNotify =
192             new ArrayList<>();
193     private final List<SensorEventListenerRecord> mSensorAccuracyListenersToNotify =
194             new ArrayList<>();
195 
196     // Persistent data store.  Must be locked each time during use.
197     private final PersistentDataStore mDataStore = new PersistentDataStore();
198 
199     // List of currently registered input devices changed listeners by process id.
200     private final Object mInputDevicesLock = new Object();
201     @GuardedBy("mInputDevicesLock")
202     private boolean mInputDevicesChangedPending;
203     @GuardedBy("mInputDevicesLock")
204     private InputDevice[] mInputDevices = new InputDevice[0];
205     @GuardedBy("mInputDevicesLock")
206     private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
207             new SparseArray<>();
208     private final ArrayList<InputDevicesChangedListenerRecord>
209             mTempInputDevicesChangedListenersToNotify = new ArrayList<>(); // handler thread only
210 
211     // State for vibrator tokens.
212     private final Object mVibratorLock = new Object();
213     private final Map<IBinder, VibratorToken> mVibratorTokens = new ArrayMap<>();
214     private int mNextVibratorTokenValue;
215 
216     // List of currently registered vibrator state changed listeners by device id.
217     @GuardedBy("mVibratorLock")
218     private final SparseArray<RemoteCallbackList<IVibratorStateListener>> mVibratorStateListeners =
219             new SparseArray<>();
220     // List of vibrator states by device id.
221     @GuardedBy("mVibratorLock")
222     private final SparseBooleanArray mIsVibrating = new SparseBooleanArray();
223     private final Object mLightLock = new Object();
224     // State for light tokens. A light token marks a lights manager session, it is generated
225     // by light session open() and deleted in session close().
226     // When lights session requests light states, the token will be used to find the light session.
227     @GuardedBy("mLightLock")
228     private final ArrayMap<IBinder, LightSession> mLightSessions = new ArrayMap<>();
229 
230     // State for lid switch
231     // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events
232     // are delivered in order. For ex, when a new lid switch callback is registered the lock is held
233     // while the callback is processing the initial lid switch event which guarantees that any
234     // events that occur at the same time are delivered after the callback has returned.
235     private final Object mLidSwitchLock = new Object();
236     @GuardedBy("mLidSwitchLock")
237     private final List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>();
238 
239     // State for the currently installed input filter.
240     final Object mInputFilterLock = new Object();
241     @GuardedBy("mInputFilterLock")
242     IInputFilter mInputFilter;
243     @GuardedBy("mInputFilterLock")
244     InputFilterHost mInputFilterHost;
245 
246     // The associations of input devices to displays by port. Maps from input device port (String)
247     // to display id (int). Currently only accessed by InputReader.
248     private final Map<String, Integer> mStaticAssociations;
249     private final Object mAssociationsLock = new Object();
250     @GuardedBy("mAssociationsLock")
251     private final Map<String, Integer> mRuntimeAssociations = new ArrayMap<>();
252 
253     // The associations of input devices to displays by port. Maps from {InputDevice#mName} (String)
254     // to {DisplayInfo#uniqueId} (String) so that events from the Input Device go to a
255     // specific display.
256     @GuardedBy("mAssociationsLock")
257     private final Map<String, String> mUniqueIdAssociationsByPort = new ArrayMap<>();
258 
259     // The associations of input devices to displays by descriptor. Maps from
260     // {InputDevice#mDescriptor} to {DisplayInfo#uniqueId} (String) so that events from the
261     // input device go to a specific display.
262     @GuardedBy("mAssociationsLock")
263     private final Map<String, String> mUniqueIdAssociationsByDescriptor = new ArrayMap<>();
264 
265     // The map from input port (String) to the keyboard layout identifiers (comma separated string
266     // containing language tag and layout type) associated with the corresponding keyboard device.
267     // Currently only accessed by InputReader.
268     @GuardedBy("mAssociationsLock")
269     private final Map<String, String> mKeyboardLayoutAssociations = new ArrayMap<>();
270 
271     // Stores input ports associated with device types. For example, adding an association
272     // {"123", "touchNavigation"} here would mean that a touch device appearing at port "123" would
273     // enumerate as a "touch navigation" device rather than the default "touchpad as a mouse
274     // pointer" device.
275     @GuardedBy("mAssociationsLock")
276     private final Map<String, String> mDeviceTypeAssociations = new ArrayMap<>();
277 
278     // Guards per-display input properties and properties relating to the mouse pointer.
279     // Threads can wait on this lock to be notified the next time the display on which the mouse
280     // pointer is shown has changed.
281     // WARNING: Do not call other services outside of input while holding this lock.
282     private final Object mAdditionalDisplayInputPropertiesLock = new Object();
283 
284     @GuardedBy("mAdditionalDisplayInputPropertiesLock")
285     private final SparseArray<AdditionalDisplayInputProperties> mAdditionalDisplayInputProperties =
286             new SparseArray<>();
287 
288     // Holds all the registered gesture monitors that are implemented as spy windows. The spy
289     // windows are mapped by their InputChannel tokens.
290     @GuardedBy("mInputMonitors")
291     final Map<IBinder, GestureMonitorSpyWindow> mInputMonitors = new HashMap<>();
292 
293     // Watches for settings changes and updates the native side appropriately.
294     private final InputSettingsObserver mSettingsObserver;
295 
296     // Manages Keyboard layouts for Physical keyboards
297     private final KeyboardLayoutManager mKeyboardLayoutManager;
298 
299     // Manages battery state for input devices.
300     private final BatteryController mBatteryController;
301 
302     // Manages Keyboard backlight
303     private final KeyboardBacklightControllerInterface mKeyboardBacklightController;
304 
305     // Manages Sticky modifier state
306     private final StickyModifierStateController mStickyModifierStateController;
307 
308     // Manages Keyboard microphone mute led
309     private final KeyboardLedController mKeyboardLedController;
310 
311     // Manages Keyboard modifier keys remapping
312     private final KeyRemapper mKeyRemapper;
313 
314     // Manages loading PointerIcons
315     private final PointerIconCache mPointerIconCache;
316 
317     // Maximum number of milliseconds to wait for input event injection.
318     private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
319 
320     // Key states (may be returned by queries about the current state of a
321     // particular key code, scan code or switch).
322 
323     /** The key state is unknown or the requested key itself is not supported. */
324     public static final int KEY_STATE_UNKNOWN = -1;
325 
326     /** The key is up. /*/
327     public static final int KEY_STATE_UP = 0;
328 
329     /** The key is down. */
330     public static final int KEY_STATE_DOWN = 1;
331 
332     /** The key is down but is a virtual key press that is being emulated by the system. */
333     public static final int KEY_STATE_VIRTUAL = 2;
334 
335     /** Scan code: Mouse / trackball button. */
336     public static final int BTN_MOUSE = 0x110;
337 
338     // Switch code values must match bionic/libc/kernel/common/linux/input.h
339     /** Switch code: Lid switch.  When set, lid is shut. */
340     public static final int SW_LID = 0x00;
341 
342     /** Switch code: Tablet mode switch.
343      * When set, the device is in tablet mode (i.e. no keyboard is connected).
344      */
345     public static final int SW_TABLET_MODE = 0x01;
346 
347     /** Switch code: Keypad slide.  When set, keyboard is exposed. */
348     public static final int SW_KEYPAD_SLIDE = 0x0a;
349 
350     /** Switch code: Headphone.  When set, headphone is inserted. */
351     public static final int SW_HEADPHONE_INSERT = 0x02;
352 
353     /** Switch code: Microphone.  When set, microphone is inserted. */
354     public static final int SW_MICROPHONE_INSERT = 0x04;
355 
356     /** Switch code: Line out.  When set, Line out (hi-Z) is inserted. */
357     public static final int SW_LINEOUT_INSERT = 0x06;
358 
359     /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
360     public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
361 
362     /** Switch code: Camera lens cover. When set the lens is covered. */
363     public static final int SW_CAMERA_LENS_COVER = 0x09;
364 
365     /** Switch code: Microphone. When set, the mic is muted. */
366     public static final int SW_MUTE_DEVICE = 0x0e;
367 
368     public static final int SW_LID_BIT = 1 << SW_LID;
369     public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
370     public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
371     public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
372     public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
373     public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
374     public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
375     public static final int SW_JACK_BITS =
376             SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
377     public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
378     public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE;
379 
380     // The following are layer numbers used for z-ordering the input overlay layers on the display.
381     // This is used for ordering layers inside {@code DisplayContent#getInputOverlayLayer()}.
382     //
383     // The layer where gesture monitors are added.
384     public static final int INPUT_OVERLAY_LAYER_GESTURE_MONITOR = 1;
385     // Place the handwriting layer above gesture monitors so that styluses cannot trigger
386     // system gestures (e.g. navigation bar, edge-back, etc) while there is an active
387     // handwriting session.
388     public static final int INPUT_OVERLAY_LAYER_HANDWRITING_SURFACE = 2;
389 
390 
391     private final String mVelocityTrackerStrategy;
392 
393     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
394     final boolean mUseDevInputEventForAudioJack;
395 
396     private final Object mFocusEventDebugViewLock = new Object();
397     @GuardedBy("mFocusEventDebugViewLock")
398     @Nullable
399     private FocusEventDebugView mFocusEventDebugView;
400     private boolean mShowKeyPresses = false;
401     private boolean mShowRotaryInput = false;
402 
403     /** Point of injection for test dependencies. */
404     @VisibleForTesting
405     static class Injector {
406         private final Context mContext;
407         private final Looper mLooper;
408         private final UEventManager mUEventManager;
409 
Injector(Context context, Looper looper, UEventManager uEventManager)410         Injector(Context context, Looper looper, UEventManager uEventManager) {
411             mContext = context;
412             mLooper = looper;
413             mUEventManager = uEventManager;
414         }
415 
getContext()416         Context getContext() {
417             return mContext;
418         }
419 
getLooper()420         Looper getLooper() {
421             return mLooper;
422         }
423 
getUEventManager()424         UEventManager getUEventManager() {
425             return mUEventManager;
426         }
427 
getNativeService(InputManagerService service)428         NativeInputManagerService getNativeService(InputManagerService service) {
429             return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
430         }
431 
registerLocalService(InputManagerInternal localService)432         void registerLocalService(InputManagerInternal localService) {
433             LocalServices.addService(InputManagerInternal.class, localService);
434         }
435     }
436 
InputManagerService(Context context)437     public InputManagerService(Context context) {
438         this(new Injector(context, DisplayThread.get().getLooper(), new UEventManager() {}));
439     }
440 
441     @VisibleForTesting
InputManagerService(Injector injector)442     InputManagerService(Injector injector) {
443         // The static association map is accessed by both java and native code, so it must be
444         // initialized before initializing the native service.
445         mStaticAssociations = loadStaticInputPortAssociations();
446 
447         mContext = injector.getContext();
448         mHandler = new InputManagerHandler(injector.getLooper());
449         mNative = injector.getNativeService(this);
450         mSettingsObserver = new InputSettingsObserver(mContext, mHandler, this, mNative);
451         mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore,
452                 injector.getLooper());
453         mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(),
454                 injector.getUEventManager());
455         mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
456                 ? new KeyboardBacklightController(mContext, mNative, mDataStore,
457                         injector.getLooper(), injector.getUEventManager())
458                 : new KeyboardBacklightControllerInterface() {};
459         mStickyModifierStateController = new StickyModifierStateController();
460         mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
461                 mNative);
462         mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
463         mPointerIconCache = new PointerIconCache(mContext, mNative);
464 
465         mUseDevInputEventForAudioJack =
466                 mContext.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
467         Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
468                 + mUseDevInputEventForAudioJack);
469 
470         String doubleTouchGestureEnablePath = mContext.getResources().getString(
471                 R.string.config_doubleTouchGestureEnableFile);
472         mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
473             new File(doubleTouchGestureEnablePath);
474 
475         mVelocityTrackerStrategy = DeviceConfig.getProperty(
476                 NAMESPACE_INPUT_NATIVE_BOOT, VELOCITYTRACKER_STRATEGY_PROPERTY);
477 
478         injector.registerLocalService(new LocalService());
479     }
480 
setWindowManagerCallbacks(WindowManagerCallbacks callbacks)481     public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
482         if (mWindowManagerCallbacks != null) {
483             unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);
484         }
485         mWindowManagerCallbacks = callbacks;
486         registerLidSwitchCallbackInternal(mWindowManagerCallbacks);
487     }
488 
setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks)489     public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
490         mWiredAccessoryCallbacks = callbacks;
491     }
492 
registerLidSwitchCallbackInternal(@onNull LidSwitchCallback callback)493     void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
494         synchronized (mLidSwitchLock) {
495             mLidSwitchCallbacks.add(callback);
496 
497             // Skip triggering the initial callback if the system is not yet ready as the switch
498             // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in
499             // systemRunning().
500             if (mSystemReady) {
501                 boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID)
502                         == KEY_STATE_UP;
503                 callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen);
504             }
505         }
506     }
507 
unregisterLidSwitchCallbackInternal(@onNull LidSwitchCallback callback)508     void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) {
509         synchronized (mLidSwitchLock) {
510             mLidSwitchCallbacks.remove(callback);
511         }
512     }
513 
start()514     public void start() {
515         Slog.i(TAG, "Starting input manager");
516         mNative.start();
517 
518         // Add ourselves to the Watchdog monitors.
519         Watchdog.getInstance().addMonitor(this);
520     }
521 
522     // TODO(BT) Pass in parameter for bluetooth system
systemRunning()523     public void systemRunning() {
524         if (DEBUG) {
525             Slog.d(TAG, "System ready.");
526         }
527 
528         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
529         mInputMethodManagerInternal =
530                 LocalServices.getService(InputMethodManagerInternal.class);
531 
532         mSettingsObserver.registerAndUpdate();
533 
534         synchronized (mLidSwitchLock) {
535             mSystemReady = true;
536 
537             // Send the initial lid switch state to any callback registered before the system was
538             // ready.
539             int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID);
540             for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
541                 LidSwitchCallback callback = mLidSwitchCallbacks.get(i);
542                 callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP);
543             }
544         }
545 
546         // Set the HW mic toggle switch state
547         final int micMuteState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY,
548                 SW_MUTE_DEVICE);
549         if (micMuteState == InputManager.SWITCH_STATE_ON) {
550             setSensorPrivacy(Sensors.MICROPHONE, true);
551         }
552         // Set the HW camera toggle switch state
553         final int cameraMuteState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY,
554                 SW_CAMERA_LENS_COVER);
555         if (cameraMuteState == InputManager.SWITCH_STATE_ON) {
556             setSensorPrivacy(Sensors.CAMERA, true);
557         }
558 
559         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
560         mContext.registerReceiver(new BroadcastReceiver() {
561             @Override
562             public void onReceive(Context context, Intent intent) {
563                 reloadDeviceAliases();
564             }
565         }, filter, null, mHandler);
566 
567         mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
568 
569         if (mWiredAccessoryCallbacks != null) {
570             mWiredAccessoryCallbacks.systemReady();
571         }
572 
573         mKeyboardLayoutManager.systemRunning();
574         mBatteryController.systemRunning();
575         mKeyboardBacklightController.systemRunning();
576         mKeyboardLedController.systemRunning();
577         mKeyRemapper.systemRunning();
578         mPointerIconCache.systemRunning();
579     }
580 
reloadDeviceAliases()581     private void reloadDeviceAliases() {
582         if (DEBUG) {
583             Slog.d(TAG, "Reloading device names.");
584         }
585         mNative.reloadDeviceAliases();
586     }
587 
setDisplayViewportsInternal(List<DisplayViewport> viewports)588     private void setDisplayViewportsInternal(List<DisplayViewport> viewports) {
589         final DisplayViewport[] vArray = new DisplayViewport[viewports.size()];
590         for (int i = viewports.size() - 1; i >= 0; --i) {
591             vArray[i] = viewports.get(i);
592         }
593         mNative.setDisplayViewports(vArray);
594 
595         // Attempt to update the default pointer display when the viewports change.
596         // Take care to not make calls to window manager while holding internal locks.
597         mNative.setPointerDisplayId(mWindowManagerCallbacks.getPointerDisplayId());
598     }
599 
600     /**
601      * Gets the current state of a key or button by key code.
602      * @param deviceId The input device id, or -1 to consult all devices.
603      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
604      * consider all input sources.  An input device is consulted if at least one of its
605      * non-class input source bits matches the specified source mask.
606      * @param keyCode The key code to check.
607      * @return The key state.
608      */
getKeyCodeState(int deviceId, int sourceMask, int keyCode)609     public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
610         return mNative.getKeyCodeState(deviceId, sourceMask, keyCode);
611     }
612 
613     /**
614      * Gets the current state of a key or button by scan code.
615      * @param deviceId The input device id, or -1 to consult all devices.
616      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
617      * consider all input sources.  An input device is consulted if at least one of its
618      * non-class input source bits matches the specified source mask.
619      * @param scanCode The scan code to check.
620      * @return The key state.
621      */
getScanCodeState(int deviceId, int sourceMask, int scanCode)622     public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
623         return mNative.getScanCodeState(deviceId, sourceMask, scanCode);
624     }
625 
626     /**
627      * Gets the current state of a switch by switch code.
628      * @param deviceId The input device id, or -1 to consult all devices.
629      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
630      * consider all input sources.  An input device is consulted if at least one of its
631      * non-class input source bits matches the specified source mask.
632      * @param switchCode The switch code to check.
633      * @return The switch state.
634      */
getSwitchState(int deviceId, int sourceMask, int switchCode)635     public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
636         return mNative.getSwitchState(deviceId, sourceMask, switchCode);
637     }
638 
639     /**
640      * Determines whether the specified key codes are supported by a particular device.
641      * @param deviceId The input device id, or -1 to consult all devices.
642      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
643      * consider all input sources.  An input device is consulted if at least one of its
644      * non-class input source bits matches the specified source mask.
645      * @param keyCodes The array of key codes to check.
646      * @param keyExists An array at least as large as keyCodes whose entries will be set
647      * to true or false based on the presence or absence of support for the corresponding
648      * key codes.
649      * @return True if the lookup was successful, false otherwise.
650      */
651     @Override // Binder call
hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists)652     public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
653         Objects.requireNonNull(keyCodes, "keyCodes must not be null");
654         Objects.requireNonNull(keyExists, "keyExists must not be null");
655         if (keyExists.length < keyCodes.length) {
656             throw new IllegalArgumentException("keyExists must be at least as large as keyCodes");
657         }
658 
659         return mNative.hasKeys(deviceId, sourceMask, keyCodes, keyExists);
660     }
661 
662     /**
663      * Returns the keyCode generated by the specified location on a US keyboard layout.
664      * This takes into consideration the currently active keyboard layout.
665      *
666      * @param deviceId The input device id.
667      * @param locationKeyCode The location of a key on a US keyboard layout.
668      * @return The KeyCode this physical key location produces.
669      */
670     @Override // Binder call
getKeyCodeForKeyLocation(int deviceId, int locationKeyCode)671     public int getKeyCodeForKeyLocation(int deviceId, int locationKeyCode) {
672         if (locationKeyCode <= KEYCODE_UNKNOWN || locationKeyCode > KeyEvent.getMaxKeyCode()) {
673             return KEYCODE_UNKNOWN;
674         }
675         return mNative.getKeyCodeForKeyLocation(deviceId, locationKeyCode);
676     }
677 
678     @Override // Binder call
getKeyCharacterMap(@onNull String layoutDescriptor)679     public KeyCharacterMap getKeyCharacterMap(@NonNull String layoutDescriptor) {
680         Objects.requireNonNull(layoutDescriptor, "layoutDescriptor must not be null");
681         return mKeyboardLayoutManager.getKeyCharacterMap(layoutDescriptor);
682     }
683 
684     /**
685      * Transfer the current touch gesture to the provided window.
686      *
687      * @param destChannelToken The token of the window or input channel that should receive the
688      * gesture
689      * @return True if the transfer succeeded, false if there was no active touch gesture happening
690      * @deprecated Use {@link #transferTouchGesture(IBinder, IBinder)}
691      */
692     @Deprecated
transferTouch(IBinder destChannelToken, int displayId)693     public boolean transferTouch(IBinder destChannelToken, int displayId) {
694         // TODO(b/162194035): Replace this with a SPY window
695         Objects.requireNonNull(destChannelToken, "destChannelToken must not be null");
696         return mNative.transferTouch(destChannelToken, displayId);
697     }
698 
699     /**
700      * Creates an input channel that will receive all input from the input dispatcher.
701      * @param inputChannelName The input channel name.
702      * @param displayId Target display id.
703      * @return The input channel.
704      */
monitorInput(String inputChannelName, int displayId)705     public InputChannel monitorInput(String inputChannelName, int displayId) {
706         Objects.requireNonNull(inputChannelName, "inputChannelName not be null");
707 
708         if (displayId < Display.DEFAULT_DISPLAY) {
709             throw new IllegalArgumentException("displayId must >= 0.");
710         }
711 
712         return mNative.createInputMonitor(displayId, inputChannelName, Binder.getCallingPid());
713     }
714 
715     @NonNull
createSpyWindowGestureMonitor(IBinder monitorToken, String name, SurfaceControl sc, int displayId, int pid, int uid)716     private InputChannel createSpyWindowGestureMonitor(IBinder monitorToken, String name,
717             SurfaceControl sc, int displayId, int pid, int uid) {
718         final InputChannel channel = createInputChannel(name);
719 
720         try {
721             monitorToken.linkToDeath(() -> removeSpyWindowGestureMonitor(channel.getToken()), 0);
722         } catch (RemoteException e) {
723             Slog.i(TAG, "Client died before '" + name + "' could be created.");
724             return null;
725         }
726         synchronized (mInputMonitors) {
727             mInputMonitors.put(channel.getToken(),
728                     new GestureMonitorSpyWindow(monitorToken, name, displayId, pid, uid, sc,
729                             channel));
730         }
731 
732         final InputChannel outInputChannel = new InputChannel();
733         channel.copyTo(outInputChannel);
734         return outInputChannel;
735     }
736 
removeSpyWindowGestureMonitor(IBinder inputChannelToken)737     private void removeSpyWindowGestureMonitor(IBinder inputChannelToken) {
738         final GestureMonitorSpyWindow monitor;
739         synchronized (mInputMonitors) {
740             monitor = mInputMonitors.remove(inputChannelToken);
741         }
742         removeInputChannel(inputChannelToken);
743         if (monitor == null) return;
744         monitor.remove();
745     }
746 
747     /**
748      * Creates an input monitor that will receive pointer events for the purposes of system-wide
749      * gesture interpretation.
750      *
751      * @param requestedName The input channel name.
752      * @param displayId Target display id.
753      * @return The input channel.
754      */
755     @Override // Binder call
monitorGestureInput(IBinder monitorToken, @NonNull String requestedName, int displayId)756     public InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName,
757             int displayId) {
758         if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
759                 "monitorGestureInput()")) {
760             throw new SecurityException("Requires MONITOR_INPUT permission");
761         }
762         Objects.requireNonNull(requestedName, "name must not be null.");
763         Objects.requireNonNull(monitorToken, "token must not be null.");
764 
765         if (displayId < Display.DEFAULT_DISPLAY) {
766             throw new IllegalArgumentException("displayId must >= 0.");
767         }
768         final String name = "[Gesture Monitor] " + requestedName;
769         final int pid = Binder.getCallingPid();
770         final int uid = Binder.getCallingUid();
771 
772         final long ident = Binder.clearCallingIdentity();
773         try {
774             final SurfaceControl sc = mWindowManagerCallbacks.createSurfaceForGestureMonitor(name,
775                     displayId);
776             if (sc == null) {
777                 throw new IllegalArgumentException(
778                         "Could not create gesture monitor surface on display: " + displayId);
779             }
780 
781             final InputChannel inputChannel = createSpyWindowGestureMonitor(
782                     monitorToken, name, sc, displayId, pid, uid);
783             return new InputMonitor(inputChannel,
784                 new InputMonitorHost(inputChannel.getToken()),
785                 new SurfaceControl(sc, "IMS.monitorGestureInput"));
786         } finally {
787             Binder.restoreCallingIdentity(ident);
788         }
789     }
790 
791     /**
792      * Creates an input channel to be used as an input event target.
793      *
794      * @param name The name of this input channel
795      */
createInputChannel(String name)796     public InputChannel createInputChannel(String name) {
797         return mNative.createInputChannel(name);
798     }
799 
800     /**
801      * Removes an input channel.
802      * @param connectionToken The input channel to unregister.
803      */
removeInputChannel(IBinder connectionToken)804     public void removeInputChannel(IBinder connectionToken) {
805         Objects.requireNonNull(connectionToken, "connectionToken must not be null");
806         mNative.removeInputChannel(connectionToken);
807     }
808 
809     /**
810      * Sets an input filter that will receive all input events before they are dispatched.
811      * The input filter may then reinterpret input events or inject new ones.
812      *
813      * To ensure consistency, the input dispatcher automatically drops all events
814      * in progress whenever an input filter is installed or uninstalled.  After an input
815      * filter is uninstalled, it can no longer send input events unless it is reinstalled.
816      * Any events it attempts to send after it has been uninstalled will be dropped.
817      *
818      * @param filter The input filter, or null to remove the current filter.
819      */
setInputFilter(IInputFilter filter)820     public void setInputFilter(IInputFilter filter) {
821         synchronized (mInputFilterLock) {
822             final IInputFilter oldFilter = mInputFilter;
823             if (oldFilter == filter) {
824                 return; // nothing to do
825             }
826 
827             if (oldFilter != null) {
828                 mInputFilter = null;
829                 mInputFilterHost.disconnectLocked();
830                 mInputFilterHost = null;
831                 try {
832                     oldFilter.uninstall();
833                 } catch (RemoteException re) {
834                     /* ignore */
835                 }
836             }
837 
838             if (filter != null) {
839                 mInputFilter = filter;
840                 mInputFilterHost = new InputFilterHost();
841                 try {
842                     filter.install(mInputFilterHost);
843                 } catch (RemoteException re) {
844                     /* ignore */
845                 }
846             }
847 
848             mNative.setInputFilterEnabled(filter != null);
849         }
850     }
851 
852     /**
853      * Set the state of the touch mode.
854      *
855      * WindowManager remains the source of truth of the touch mode state.
856      * However, we need to keep a copy of this state in input.
857      *
858      * The apps determine the touch mode state. Therefore, a single app will
859      * affect the global state. That state change needs to be propagated to
860      * other apps, when they become focused.
861      *
862      * When input dispatches focus to the apps, the touch mode state
863      * will be sent together with the focus change (but each one in its own event).
864      *
865      * @param inTouchMode   true if the device is in touch mode
866      * @param pid           the pid of the process that requested to switch touch mode state
867      * @param uid           the uid of the process that requested to switch touch mode state
868      * @param hasPermission if set to {@code true} then no further authorization will be performed
869      * @param displayId     the target display (ignored if device is configured with per display
870      *                      touch mode enabled)
871      * @return {@code true} if the touch mode was successfully changed, {@code false} otherwise
872      */
setInTouchMode(boolean inTouchMode, int pid, int uid, boolean hasPermission, int displayId)873     public boolean setInTouchMode(boolean inTouchMode, int pid, int uid, boolean hasPermission,
874             int displayId) {
875         return mNative.setInTouchMode(inTouchMode, pid, uid, hasPermission, displayId);
876     }
877 
878     @Override // Binder call
injectInputEvent(InputEvent event, int mode)879     public boolean injectInputEvent(InputEvent event, int mode) {
880         return injectInputEventToTarget(event, mode, Process.INVALID_UID);
881     }
882 
883     @Override // Binder call
injectInputEventToTarget(InputEvent event, int mode, int targetUid)884     public boolean injectInputEventToTarget(InputEvent event, int mode, int targetUid) {
885         if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
886                 "injectInputEvent()", true /*checkInstrumentationSource*/)) {
887             throw new SecurityException(
888                     "Injecting input events requires the caller (or the source of the "
889                             + "instrumentation, if any) to have the INJECT_EVENTS permission.");
890         }
891         // We are not checking if targetUid matches the callingUid, since having the permission
892         // already means you can inject into any window.
893         Objects.requireNonNull(event, "event must not be null");
894         if (mode != InputEventInjectionSync.NONE
895                 && mode != InputEventInjectionSync.WAIT_FOR_FINISHED
896                 && mode != InputEventInjectionSync.WAIT_FOR_RESULT) {
897             throw new IllegalArgumentException("mode is invalid");
898         }
899 
900         final int pid = Binder.getCallingPid();
901         final long ident = Binder.clearCallingIdentity();
902         final boolean injectIntoUid = targetUid != Process.INVALID_UID;
903         final int result;
904         try {
905             result = mNative.injectInputEvent(event, injectIntoUid,
906                     targetUid, mode, INJECTION_TIMEOUT_MILLIS,
907                     WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
908         } finally {
909             Binder.restoreCallingIdentity(ident);
910         }
911         switch (result) {
912             case InputEventInjectionResult.SUCCEEDED:
913                 return true;
914             case InputEventInjectionResult.TARGET_MISMATCH:
915                 if (!injectIntoUid) {
916                     throw new IllegalStateException("Injection should not result in TARGET_MISMATCH"
917                             + " when it is not targeted into to a specific uid.");
918                 }
919                 throw new IllegalArgumentException(
920                     "Targeted input event injection from pid " + pid
921                             + " was not directed at a window owned by uid "
922                             + targetUid + ".");
923             case InputEventInjectionResult.TIMED_OUT:
924                 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
925                 return false;
926             case InputEventInjectionResult.FAILED:
927             default:
928                 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
929                 return false;
930         }
931     }
932 
933     @Override // Binder call
verifyInputEvent(InputEvent event)934     public VerifiedInputEvent verifyInputEvent(InputEvent event) {
935         Objects.requireNonNull(event, "event must not be null");
936         return mNative.verifyInputEvent(event);
937     }
938 
939     @Override // Binder call
getVelocityTrackerStrategy()940     public String getVelocityTrackerStrategy() {
941         return mVelocityTrackerStrategy;
942     }
943 
944     /**
945      * Gets information about the input device with the specified id.
946      * @param deviceId The device id.
947      * @return The input device or null if not found.
948      */
949     @Override // Binder call
getInputDevice(int deviceId)950     public InputDevice getInputDevice(int deviceId) {
951         synchronized (mInputDevicesLock) {
952             for (final InputDevice inputDevice : mInputDevices) {
953                 if (inputDevice.getId() == deviceId) {
954                     return inputDevice;
955                 }
956             }
957         }
958         return null;
959     }
960 
961     // Binder call
962     @Override
enableInputDevice(int deviceId)963     public void enableInputDevice(int deviceId) {
964         if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE,
965                 "enableInputDevice()")) {
966             throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission");
967         }
968         mNative.enableInputDevice(deviceId);
969     }
970 
971     // Binder call
972     @Override
disableInputDevice(int deviceId)973     public void disableInputDevice(int deviceId) {
974         if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE,
975                 "disableInputDevice()")) {
976             throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission");
977         }
978         mNative.disableInputDevice(deviceId);
979     }
980 
981     /**
982      * Gets the ids of all input devices in the system.
983      * @return The input device ids.
984      */
985     @Override // Binder call
getInputDeviceIds()986     public int[] getInputDeviceIds() {
987         synchronized (mInputDevicesLock) {
988             final int count = mInputDevices.length;
989             int[] ids = new int[count];
990             for (int i = 0; i < count; i++) {
991                 ids[i] = mInputDevices[i].getId();
992             }
993             return ids;
994         }
995     }
996 
997     /**
998      * Gets all input devices in the system.
999      * @return The array of input devices.
1000      */
getInputDevices()1001     public InputDevice[] getInputDevices() {
1002         synchronized (mInputDevicesLock) {
1003             return mInputDevices;
1004         }
1005     }
1006 
1007     @Override // Binder call
registerInputDevicesChangedListener(IInputDevicesChangedListener listener)1008     public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
1009         Objects.requireNonNull(listener, "listener must not be null");
1010 
1011         synchronized (mInputDevicesLock) {
1012             int callingPid = Binder.getCallingPid();
1013             if (mInputDevicesChangedListeners.get(callingPid) != null) {
1014                 throw new SecurityException("The calling process has already "
1015                         + "registered an InputDevicesChangedListener.");
1016             }
1017 
1018             InputDevicesChangedListenerRecord record =
1019                     new InputDevicesChangedListenerRecord(callingPid, listener);
1020             try {
1021                 IBinder binder = listener.asBinder();
1022                 binder.linkToDeath(record, 0);
1023             } catch (RemoteException ex) {
1024                 // give up
1025                 throw new RuntimeException(ex);
1026             }
1027 
1028             mInputDevicesChangedListeners.put(callingPid, record);
1029         }
1030     }
1031 
onInputDevicesChangedListenerDied(int pid)1032     private void onInputDevicesChangedListenerDied(int pid) {
1033         synchronized (mInputDevicesLock) {
1034             mInputDevicesChangedListeners.remove(pid);
1035         }
1036     }
1037 
1038     // Must be called on handler.
deliverInputDevicesChanged(InputDevice[] oldInputDevices)1039     private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
1040         // Scan for changes.
1041         mTempInputDevicesChangedListenersToNotify.clear();
1042         final int numListeners;
1043         final int[] deviceIdAndGeneration;
1044         synchronized (mInputDevicesLock) {
1045             if (!mInputDevicesChangedPending) {
1046                 return;
1047             }
1048             mInputDevicesChangedPending = false;
1049 
1050             numListeners = mInputDevicesChangedListeners.size();
1051             for (int i = 0; i < numListeners; i++) {
1052                 mTempInputDevicesChangedListenersToNotify.add(
1053                         mInputDevicesChangedListeners.valueAt(i));
1054             }
1055 
1056             final int numDevices = mInputDevices.length;
1057             deviceIdAndGeneration = new int[numDevices * 2];
1058             for (int i = 0; i < numDevices; i++) {
1059                 final InputDevice inputDevice = mInputDevices[i];
1060                 deviceIdAndGeneration[i * 2] = inputDevice.getId();
1061                 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
1062                 if (DEBUG) {
1063                     Log.d(TAG, "device " + inputDevice.getId() + " generation "
1064                             + inputDevice.getGeneration());
1065                 }
1066             }
1067         }
1068 
1069         // Notify listeners.
1070         for (int i = 0; i < numListeners; i++) {
1071             mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
1072                     deviceIdAndGeneration);
1073         }
1074         mTempInputDevicesChangedListenersToNotify.clear();
1075     }
1076 
1077     @Override // Binder call & native callback
getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation)1078     public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
1079             int surfaceRotation) {
1080         Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null");
1081 
1082         synchronized (mDataStore) {
1083             return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
1084         }
1085     }
1086 
1087     @Override // Binder call
setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation, TouchCalibration calibration)1088     public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
1089             TouchCalibration calibration) {
1090         if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
1091                 "setTouchCalibrationForInputDevice()")) {
1092             throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
1093         }
1094         Objects.requireNonNull(inputDeviceDescriptor, "inputDeviceDescriptor must not be null");
1095         Objects.requireNonNull(calibration, "calibration must not be null");
1096         if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
1097             throw new IllegalArgumentException("surfaceRotation value out of bounds");
1098         }
1099 
1100         synchronized (mDataStore) {
1101             try {
1102                 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
1103                         calibration)) {
1104                     mNative.reloadCalibration();
1105                 }
1106             } finally {
1107                 mDataStore.saveIfNeeded();
1108             }
1109         }
1110     }
1111 
1112     @Override // Binder call
isInTabletMode()1113     public int isInTabletMode() {
1114         if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE,
1115                 "isInTabletMode()")) {
1116             throw new SecurityException("Requires TABLET_MODE permission");
1117         }
1118         return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_TABLET_MODE);
1119     }
1120 
1121     @Override // Binder call
isMicMuted()1122     public int isMicMuted() {
1123         return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MUTE_DEVICE);
1124     }
1125 
1126     @Override // Binder call
registerTabletModeChangedListener(ITabletModeChangedListener listener)1127     public void registerTabletModeChangedListener(ITabletModeChangedListener listener) {
1128         if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE,
1129                 "registerTabletModeChangedListener()")) {
1130             throw new SecurityException("Requires TABLET_MODE_LISTENER permission");
1131         }
1132         Objects.requireNonNull(listener, "event must not be null");
1133 
1134         synchronized (mTabletModeLock) {
1135             final int callingPid = Binder.getCallingPid();
1136             if (mTabletModeChangedListeners.get(callingPid) != null) {
1137                 throw new IllegalStateException("The calling process has already registered "
1138                         + "a TabletModeChangedListener.");
1139             }
1140             TabletModeChangedListenerRecord record =
1141                     new TabletModeChangedListenerRecord(callingPid, listener);
1142             try {
1143                 IBinder binder = listener.asBinder();
1144                 binder.linkToDeath(record, 0);
1145             } catch (RemoteException ex) {
1146                 throw new RuntimeException(ex);
1147             }
1148             mTabletModeChangedListeners.put(callingPid, record);
1149         }
1150     }
1151 
onTabletModeChangedListenerDied(int pid)1152     private void onTabletModeChangedListenerDied(int pid) {
1153         synchronized (mTabletModeLock) {
1154             mTabletModeChangedListeners.remove(pid);
1155         }
1156     }
1157 
1158     // Must be called on handler
deliverTabletModeChanged(long whenNanos, boolean inTabletMode)1159     private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) {
1160         mTempTabletModeChangedListenersToNotify.clear();
1161         final int numListeners;
1162         synchronized (mTabletModeLock) {
1163             numListeners = mTabletModeChangedListeners.size();
1164             for (int i = 0; i < numListeners; i++) {
1165                 mTempTabletModeChangedListenersToNotify.add(
1166                         mTabletModeChangedListeners.valueAt(i));
1167             }
1168         }
1169         for (int i = 0; i < numListeners; i++) {
1170             mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged(
1171                     whenNanos, inTabletMode);
1172         }
1173     }
1174 
1175     @Override // Binder call
getKeyboardLayouts()1176     public KeyboardLayout[] getKeyboardLayouts() {
1177         return mKeyboardLayoutManager.getKeyboardLayouts();
1178     }
1179 
1180     @Override // Binder call
getKeyboardLayout(String keyboardLayoutDescriptor)1181     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
1182         return mKeyboardLayoutManager.getKeyboardLayout(keyboardLayoutDescriptor);
1183     }
1184 
1185     @Override // Binder call
getKeyboardLayoutForInputDevice( InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype)1186     public KeyboardLayoutSelectionResult getKeyboardLayoutForInputDevice(
1187             InputDeviceIdentifier identifier, @UserIdInt int userId,
1188             @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype) {
1189         return mKeyboardLayoutManager.getKeyboardLayoutForInputDevice(identifier, userId,
1190                 imeInfo, imeSubtype);
1191     }
1192 
1193     @EnforcePermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
1194     @Override // Binder call
setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor)1195     public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1196             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
1197             @Nullable InputMethodSubtype imeSubtype, String keyboardLayoutDescriptor) {
1198         super.setKeyboardLayoutForInputDevice_enforcePermission();
1199         mKeyboardLayoutManager.setKeyboardLayoutForInputDevice(identifier, userId, imeInfo,
1200                 imeSubtype, keyboardLayoutDescriptor);
1201     }
1202 
1203     @Override // Binder call
getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier, @UserIdInt int userId, @NonNull InputMethodInfo imeInfo, @Nullable InputMethodSubtype imeSubtype)1204     public KeyboardLayout[] getKeyboardLayoutListForInputDevice(InputDeviceIdentifier identifier,
1205             @UserIdInt int userId, @NonNull InputMethodInfo imeInfo,
1206             @Nullable InputMethodSubtype imeSubtype) {
1207         return mKeyboardLayoutManager.getKeyboardLayoutListForInputDevice(identifier, userId,
1208                 imeInfo, imeSubtype);
1209     }
1210 
setFocusedApplication(int displayId, InputApplicationHandle application)1211     public void setFocusedApplication(int displayId, InputApplicationHandle application) {
1212         mNative.setFocusedApplication(displayId, application);
1213     }
1214 
setFocusedDisplay(int displayId)1215     public void setFocusedDisplay(int displayId) {
1216         mNative.setFocusedDisplay(displayId);
1217     }
1218 
1219     /** Clean up input window handles of the given display. */
onDisplayRemoved(int displayId)1220     public void onDisplayRemoved(int displayId) {
1221         updateAdditionalDisplayInputProperties(displayId, AdditionalDisplayInputProperties::reset);
1222 
1223         // TODO(b/320763728): Rely on WindowInfosListener to determine when a display has been
1224         //  removed in InputDispatcher instead of this callback.
1225         mNative.displayRemoved(displayId);
1226     }
1227 
1228     @Override
requestPointerCapture(IBinder inputChannelToken, boolean enabled)1229     public void requestPointerCapture(IBinder inputChannelToken, boolean enabled) {
1230         Objects.requireNonNull(inputChannelToken, "event must not be null");
1231 
1232         mNative.requestPointerCapture(inputChannelToken, enabled);
1233     }
1234 
setInputDispatchMode(boolean enabled, boolean frozen)1235     public void setInputDispatchMode(boolean enabled, boolean frozen) {
1236         mNative.setInputDispatchMode(enabled, frozen);
1237     }
1238 
setSystemUiLightsOut(boolean lightsOut)1239     public void setSystemUiLightsOut(boolean lightsOut) {
1240         mNative.setSystemUiLightsOut(lightsOut);
1241     }
1242 
1243     /**
1244      * Start drag and drop.
1245      *
1246      * @param fromChannel The input channel that is currently receiving a touch gesture that should
1247      *                    be turned into the drag pointer.
1248      * @param dragAndDropChannel The input channel associated with the system drag window.
1249      * @return true if drag and drop was successfully started, false otherwise.
1250      */
startDragAndDrop(@onNull InputChannel fromChannel, @NonNull InputChannel dragAndDropChannel)1251     public boolean startDragAndDrop(@NonNull InputChannel fromChannel,
1252             @NonNull InputChannel dragAndDropChannel) {
1253         return mNative.transferTouchGesture(fromChannel.getToken(), dragAndDropChannel.getToken(),
1254                 true /* isDragDrop */);
1255     }
1256 
1257     /**
1258      * Atomically transfers an active touch gesture from one window to another, as identified by
1259      * their input channels.
1260      *
1261      * <p>Only the touch gesture that is currently being dispatched to a window associated with
1262      * {@code fromChannelToken} will be effected. That window will no longer receive
1263      * the touch gesture (i.e. it will receive {@link android.view.MotionEvent#ACTION_CANCEL}).
1264      * A window associated with the {@code toChannelToken} will receive the rest of the gesture
1265      * (i.e. beginning with {@link android.view.MotionEvent#ACTION_DOWN} or
1266      * {@link android.view.MotionEvent#ACTION_POINTER_DOWN}).
1267      *
1268      * <p>Transferring touch gestures will have no impact on focused windows. If the {@code
1269      * toChannelToken} window is focusable, this will not bring focus to that window.
1270      *
1271      * @param fromChannelToken The channel token of a window that has an active touch gesture.
1272      * @param toChannelToken The channel token of the window that should receive the gesture in
1273      *   place of the first.
1274      * @return True if the transfer was successful. False if the specified windows don't exist, or
1275      *   if the source window is not actively receiving a touch gesture at the time of the request.
1276      */
transferTouchGesture(@onNull IBinder fromChannelToken, @NonNull IBinder toChannelToken)1277     public boolean transferTouchGesture(@NonNull IBinder fromChannelToken,
1278             @NonNull IBinder toChannelToken) {
1279         Objects.requireNonNull(fromChannelToken);
1280         Objects.requireNonNull(toChannelToken);
1281         return mNative.transferTouchGesture(fromChannelToken, toChannelToken,
1282                 false /* isDragDrop */);
1283     }
1284 
1285     @Override // Binder call
getMousePointerSpeed()1286     public int getMousePointerSpeed() {
1287         return mNative.getMousePointerSpeed();
1288     }
1289 
1290     @Override // Binder call
tryPointerSpeed(int speed)1291     public void tryPointerSpeed(int speed) {
1292         if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1293                 "tryPointerSpeed()")) {
1294             throw new SecurityException("Requires SET_POINTER_SPEED permission");
1295         }
1296 
1297         if (speed < InputSettings.MIN_POINTER_SPEED || speed > InputSettings.MAX_POINTER_SPEED) {
1298             throw new IllegalArgumentException("speed out of range");
1299         }
1300 
1301         setPointerSpeedUnchecked(speed);
1302     }
1303 
setPointerSpeedUnchecked(int speed)1304     private void setPointerSpeedUnchecked(int speed) {
1305         speed = Math.min(Math.max(speed, InputSettings.MIN_POINTER_SPEED),
1306                 InputSettings.MAX_POINTER_SPEED);
1307         mNative.setPointerSpeed(speed);
1308     }
1309 
setMousePointerAccelerationEnabled(boolean enabled, int displayId)1310     private void setMousePointerAccelerationEnabled(boolean enabled, int displayId) {
1311         updateAdditionalDisplayInputProperties(displayId,
1312                 properties -> properties.mousePointerAccelerationEnabled = enabled);
1313     }
1314 
setPointerIconVisible(boolean visible, int displayId)1315     private void setPointerIconVisible(boolean visible, int displayId) {
1316         updateAdditionalDisplayInputProperties(displayId,
1317                 properties -> properties.pointerIconVisible = visible);
1318     }
1319 
setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible)1320     private void setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible) {
1321         mNative.setDisplayEligibilityForPointerCapture(displayId, isEligible);
1322     }
1323 
1324     private static class VibrationInfo {
1325         private final long[] mPattern;
1326         private final int[] mAmplitudes;
1327         private final int mRepeat;
1328 
getPattern()1329         public long[] getPattern() {
1330             return mPattern;
1331         }
1332 
getAmplitudes()1333         public int[] getAmplitudes() {
1334             return mAmplitudes;
1335         }
1336 
getRepeatIndex()1337         public int getRepeatIndex() {
1338             return mRepeat;
1339         }
1340 
VibrationInfo(VibrationEffect effect)1341         VibrationInfo(VibrationEffect effect) {
1342             long[] pattern = null;
1343             int[] amplitudes = null;
1344             int patternRepeatIndex = -1;
1345             int amplitudeCount = -1;
1346 
1347             if (effect instanceof VibrationEffect.Composed) {
1348                 VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
1349                 int segmentCount = composed.getSegments().size();
1350                 pattern = new long[segmentCount];
1351                 amplitudes = new int[segmentCount];
1352                 patternRepeatIndex = composed.getRepeatIndex();
1353                 amplitudeCount = 0;
1354                 for (int i = 0; i < segmentCount; i++) {
1355                     VibrationEffectSegment segment = composed.getSegments().get(i);
1356                     if (composed.getRepeatIndex() == i) {
1357                         patternRepeatIndex = amplitudeCount;
1358                     }
1359                     if (!(segment instanceof StepSegment)) {
1360                         Slog.w(TAG, "Input devices don't support segment " + segment);
1361                         amplitudeCount = -1;
1362                         break;
1363                     }
1364                     float amplitude = ((StepSegment) segment).getAmplitude();
1365                     if (Float.compare(amplitude, VibrationEffect.DEFAULT_AMPLITUDE) == 0) {
1366                         amplitudes[amplitudeCount] = DEFAULT_VIBRATION_MAGNITUDE;
1367                     } else {
1368                         amplitudes[amplitudeCount] =
1369                                 (int) (amplitude * VibrationEffect.MAX_AMPLITUDE);
1370                     }
1371                     pattern[amplitudeCount++] = segment.getDuration();
1372                 }
1373             }
1374 
1375             if (amplitudeCount < 0) {
1376                 Slog.w(TAG, "Only oneshot and step waveforms are supported on input devices");
1377                 mPattern = new long[0];
1378                 mAmplitudes = new int[0];
1379                 mRepeat = -1;
1380             } else {
1381                 mRepeat = patternRepeatIndex;
1382                 mPattern = new long[amplitudeCount];
1383                 mAmplitudes = new int[amplitudeCount];
1384                 System.arraycopy(pattern, 0, mPattern, 0, amplitudeCount);
1385                 System.arraycopy(amplitudes, 0, mAmplitudes, 0, amplitudeCount);
1386                 if (mRepeat >= mPattern.length) {
1387                     throw new ArrayIndexOutOfBoundsException("Repeat index " + mRepeat
1388                             + " must be within the bounds of the pattern.length "
1389                             + mPattern.length);
1390                 }
1391             }
1392         }
1393     }
1394 
getVibratorToken(int deviceId, IBinder token)1395     private VibratorToken getVibratorToken(int deviceId, IBinder token) {
1396         VibratorToken v;
1397         synchronized (mVibratorLock) {
1398             v = mVibratorTokens.get(token);
1399             if (v == null) {
1400                 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1401                 try {
1402                     token.linkToDeath(v, 0);
1403                 } catch (RemoteException ex) {
1404                     // give up
1405                     throw new RuntimeException(ex);
1406                 }
1407                 mVibratorTokens.put(token, v);
1408             }
1409         }
1410         return v;
1411     }
1412 
1413     // Binder call
1414     @Override
vibrate(int deviceId, VibrationEffect effect, IBinder token)1415     public void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
1416         VibrationInfo info = new VibrationInfo(effect);
1417         VibratorToken v = getVibratorToken(deviceId, token);
1418         synchronized (v) {
1419             v.mVibrating = true;
1420             mNative.vibrate(deviceId, info.getPattern(), info.getAmplitudes(),
1421                     info.getRepeatIndex(), v.mTokenValue);
1422         }
1423     }
1424 
1425     // Binder call
1426     @Override
getVibratorIds(int deviceId)1427     public int[] getVibratorIds(int deviceId) {
1428         return mNative.getVibratorIds(deviceId);
1429     }
1430 
1431     // Binder call
1432     @Override
isVibrating(int deviceId)1433     public boolean isVibrating(int deviceId) {
1434         return mNative.isVibrating(deviceId);
1435     }
1436 
1437     // Binder call
1438     @Override
vibrateCombined(int deviceId, CombinedVibration effect, IBinder token)1439     public void vibrateCombined(int deviceId, CombinedVibration effect, IBinder token) {
1440         VibratorToken v = getVibratorToken(deviceId, token);
1441         synchronized (v) {
1442             if (!(effect instanceof CombinedVibration.Mono)
1443                     && !(effect instanceof CombinedVibration.Stereo)) {
1444                 Slog.e(TAG, "Only Mono and Stereo effects are supported");
1445                 return;
1446             }
1447 
1448             v.mVibrating = true;
1449             if (effect instanceof CombinedVibration.Mono) {
1450                 CombinedVibration.Mono mono = (CombinedVibration.Mono) effect;
1451                 VibrationInfo info = new VibrationInfo(mono.getEffect());
1452                 mNative.vibrate(deviceId, info.getPattern(), info.getAmplitudes(),
1453                         info.getRepeatIndex(), v.mTokenValue);
1454             } else if (effect instanceof CombinedVibration.Stereo) {
1455                 CombinedVibration.Stereo stereo = (CombinedVibration.Stereo) effect;
1456                 SparseArray<VibrationEffect> effects = stereo.getEffects();
1457                 long[] pattern = new long[0];
1458                 int repeat = Integer.MIN_VALUE;
1459                 SparseArray<int[]> amplitudes = new SparseArray<>(effects.size());
1460                 for (int i = 0; i < effects.size(); i++) {
1461                     VibrationInfo info = new VibrationInfo(effects.valueAt(i));
1462                     // Pattern of all effects should be same
1463                     if (pattern.length == 0) {
1464                         pattern = info.getPattern();
1465                     }
1466                     if (repeat == Integer.MIN_VALUE) {
1467                         repeat = info.getRepeatIndex();
1468                     }
1469                     amplitudes.put(effects.keyAt(i), info.getAmplitudes());
1470                 }
1471                 mNative.vibrateCombined(deviceId, pattern, amplitudes, repeat,
1472                         v.mTokenValue);
1473             }
1474         }
1475     }
1476 
1477     // Binder call
1478     @Override
cancelVibrate(int deviceId, IBinder token)1479     public void cancelVibrate(int deviceId, IBinder token) {
1480         VibratorToken v;
1481         synchronized (mVibratorLock) {
1482             v = mVibratorTokens.get(token);
1483             if (v == null || v.mDeviceId != deviceId) {
1484                 return; // nothing to cancel
1485             }
1486         }
1487 
1488         cancelVibrateIfNeeded(v);
1489     }
1490 
onVibratorTokenDied(VibratorToken v)1491     void onVibratorTokenDied(VibratorToken v) {
1492         synchronized (mVibratorLock) {
1493             mVibratorTokens.remove(v.mToken);
1494         }
1495 
1496         cancelVibrateIfNeeded(v);
1497     }
1498 
cancelVibrateIfNeeded(VibratorToken v)1499     private void cancelVibrateIfNeeded(VibratorToken v) {
1500         synchronized (v) {
1501             if (v.mVibrating) {
1502                 mNative.cancelVibrate(v.mDeviceId, v.mTokenValue);
1503                 v.mVibrating = false;
1504             }
1505         }
1506     }
1507 
1508     // Native callback.
1509     @SuppressWarnings("unused")
notifyVibratorState(int deviceId, boolean isOn)1510     private void notifyVibratorState(int deviceId, boolean isOn) {
1511         if (DEBUG) {
1512             Slog.d(TAG, "notifyVibratorState: deviceId=" + deviceId + " isOn=" + isOn);
1513         }
1514         synchronized (mVibratorLock) {
1515             mIsVibrating.put(deviceId, isOn);
1516             notifyVibratorStateListenersLocked(deviceId);
1517         }
1518     }
1519 
1520     @GuardedBy("mVibratorLock")
notifyVibratorStateListenersLocked(int deviceId)1521     private void notifyVibratorStateListenersLocked(int deviceId) {
1522         if (!mVibratorStateListeners.contains(deviceId)) {
1523             if (DEBUG) {
1524                 Slog.v(TAG, "Device " + deviceId + " doesn't have vibrator state listener.");
1525             }
1526             return;
1527         }
1528         RemoteCallbackList<IVibratorStateListener> listeners =
1529                 mVibratorStateListeners.get(deviceId);
1530         final int length = listeners.beginBroadcast();
1531         try {
1532             for (int i = 0; i < length; i++) {
1533                 notifyVibratorStateListenerLocked(deviceId, listeners.getBroadcastItem(i));
1534             }
1535         } finally {
1536             listeners.finishBroadcast();
1537         }
1538     }
1539 
1540     @GuardedBy("mVibratorLock")
notifyVibratorStateListenerLocked(int deviceId, IVibratorStateListener listener)1541     private void notifyVibratorStateListenerLocked(int deviceId, IVibratorStateListener listener) {
1542         try {
1543             listener.onVibrating(mIsVibrating.get(deviceId));
1544         } catch (RemoteException | RuntimeException e) {
1545             Slog.e(TAG, "Vibrator state listener failed to call", e);
1546         }
1547     }
1548 
1549     @Override // Binder call
registerVibratorStateListener(int deviceId, IVibratorStateListener listener)1550     public boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
1551         Objects.requireNonNull(listener, "listener must not be null");
1552 
1553         RemoteCallbackList<IVibratorStateListener> listeners;
1554         synchronized (mVibratorLock) {
1555             if (!mVibratorStateListeners.contains(deviceId)) {
1556                 listeners = new RemoteCallbackList<>();
1557                 mVibratorStateListeners.put(deviceId, listeners);
1558             } else {
1559                 listeners = mVibratorStateListeners.get(deviceId);
1560             }
1561 
1562             final long token = Binder.clearCallingIdentity();
1563             try {
1564                 if (!listeners.register(listener)) {
1565                     Slog.e(TAG, "Could not register vibrator state listener " + listener);
1566                     return false;
1567                 }
1568                 // Notify its callback after new client registered.
1569                 notifyVibratorStateListenerLocked(deviceId, listener);
1570                 return true;
1571             } finally {
1572                 Binder.restoreCallingIdentity(token);
1573             }
1574         }
1575     }
1576 
1577     @Override // Binder call
unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener)1578     public boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
1579         synchronized (mVibratorLock) {
1580             final long token = Binder.clearCallingIdentity();
1581             try {
1582                 if (!mVibratorStateListeners.contains(deviceId)) {
1583                     Slog.w(TAG, "Vibrator state listener " + deviceId + " doesn't exist");
1584                     return false;
1585                 }
1586                 RemoteCallbackList<IVibratorStateListener> listeners =
1587                         mVibratorStateListeners.get(deviceId);
1588                 return listeners.unregister(listener);
1589             } finally {
1590                 Binder.restoreCallingIdentity(token);
1591             }
1592         }
1593     }
1594 
1595     // Binder call
1596     @Override
getBatteryState(int deviceId)1597     public IInputDeviceBatteryState getBatteryState(int deviceId) {
1598         return mBatteryController.getBatteryState(deviceId);
1599     }
1600 
1601     // Binder call
1602     @Override
setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId, IBinder inputToken)1603     public boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId,
1604             IBinder inputToken) {
1605         Objects.requireNonNull(icon);
1606         return mNative.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken);
1607     }
1608 
1609     /**
1610      * Add a runtime association between the input port and the display port. This overrides any
1611      * static associations.
1612      * @param inputPort the port of the input device
1613      * @param displayPort the physical port of the associated display
1614      */
1615     @Override // Binder call
addPortAssociation(@onNull String inputPort, int displayPort)1616     public void addPortAssociation(@NonNull String inputPort, int displayPort) {
1617         if (!checkCallingPermission(
1618                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1619                 "addPortAssociation()")) {
1620             throw new SecurityException(
1621                     "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1622         }
1623 
1624         Objects.requireNonNull(inputPort);
1625         synchronized (mAssociationsLock) {
1626             mRuntimeAssociations.put(inputPort, displayPort);
1627         }
1628         mNative.notifyPortAssociationsChanged();
1629     }
1630 
1631     /**
1632      * Remove the runtime association between the input port and the display port. Any existing
1633      * static association for the cleared input port will be restored.
1634      * @param inputPort the port of the input device to be cleared
1635      */
1636     @Override // Binder call
removePortAssociation(@onNull String inputPort)1637     public void removePortAssociation(@NonNull String inputPort) {
1638         if (!checkCallingPermission(
1639                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1640                 "removePortAssociation()")) {
1641             throw new SecurityException(
1642                     "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1643         }
1644 
1645         Objects.requireNonNull(inputPort);
1646         synchronized (mAssociationsLock) {
1647             mRuntimeAssociations.remove(inputPort);
1648         }
1649         mNative.notifyPortAssociationsChanged();
1650     }
1651 
1652     @Override // Binder call
addUniqueIdAssociationByPort(@onNull String inputPort, @NonNull String displayUniqueId)1653     public void addUniqueIdAssociationByPort(@NonNull String inputPort,
1654             @NonNull String displayUniqueId) {
1655         if (!checkCallingPermission(
1656                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1657                 "addUniqueIdAssociation()")) {
1658             throw new SecurityException(
1659                     "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1660         }
1661 
1662         Objects.requireNonNull(inputPort);
1663         Objects.requireNonNull(displayUniqueId);
1664         synchronized (mAssociationsLock) {
1665             mUniqueIdAssociationsByPort.put(inputPort, displayUniqueId);
1666         }
1667         mNative.changeUniqueIdAssociation();
1668     }
1669 
1670     @Override // Binder call
removeUniqueIdAssociationByPort(@onNull String inputPort)1671     public void removeUniqueIdAssociationByPort(@NonNull String inputPort) {
1672         if (!checkCallingPermission(
1673                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1674                 "removeUniqueIdAssociation()")) {
1675             throw new SecurityException("Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1676         }
1677 
1678         Objects.requireNonNull(inputPort);
1679         synchronized (mAssociationsLock) {
1680             mUniqueIdAssociationsByPort.remove(inputPort);
1681         }
1682         mNative.changeUniqueIdAssociation();
1683     }
1684 
1685     /**
1686      * Adds a runtime association between the input device descriptor and the display unique id.
1687      * @param inputDeviceDescriptor the descriptor of the input device
1688      * @param displayUniqueId the unique ID of the display
1689      */
1690     @Override // Binder call
addUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor, @NonNull String displayUniqueId)1691     public void addUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor,
1692                                                    @NonNull String displayUniqueId) {
1693         if (!checkCallingPermission(
1694                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1695                 "addUniqueIdAssociationByDescriptor()")) {
1696             throw new SecurityException(
1697                     "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1698         }
1699 
1700         Objects.requireNonNull(inputDeviceDescriptor);
1701         Objects.requireNonNull(displayUniqueId);
1702         synchronized (mAssociationsLock) {
1703             mUniqueIdAssociationsByDescriptor.put(inputDeviceDescriptor, displayUniqueId);
1704         }
1705         mNative.changeUniqueIdAssociation();
1706     }
1707 
1708     /**
1709      * Removes the runtime association between the input device and the display.
1710      * @param inputDeviceDescriptor the descriptor of the input device
1711      */
1712     @Override // Binder call
removeUniqueIdAssociationByDescriptor(@onNull String inputDeviceDescriptor)1713     public void removeUniqueIdAssociationByDescriptor(@NonNull String inputDeviceDescriptor) {
1714         if (!checkCallingPermission(
1715                 android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
1716                 "removeUniqueIdAssociationByDescriptor()")) {
1717             throw new SecurityException(
1718                     "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
1719         }
1720 
1721         Objects.requireNonNull(inputDeviceDescriptor);
1722         synchronized (mAssociationsLock) {
1723             mUniqueIdAssociationsByDescriptor.remove(inputDeviceDescriptor);
1724         }
1725         mNative.changeUniqueIdAssociation();
1726     }
1727 
setTypeAssociationInternal(@onNull String inputPort, @NonNull String type)1728     void setTypeAssociationInternal(@NonNull String inputPort, @NonNull String type) {
1729         Objects.requireNonNull(inputPort);
1730         Objects.requireNonNull(type);
1731         synchronized (mAssociationsLock) {
1732             mDeviceTypeAssociations.put(inputPort, type);
1733         }
1734         mNative.changeTypeAssociation();
1735     }
1736 
unsetTypeAssociationInternal(@onNull String inputPort)1737     void unsetTypeAssociationInternal(@NonNull String inputPort) {
1738         Objects.requireNonNull(inputPort);
1739         synchronized (mAssociationsLock) {
1740             mDeviceTypeAssociations.remove(inputPort);
1741         }
1742         mNative.changeTypeAssociation();
1743     }
1744 
addKeyboardLayoutAssociation(@onNull String inputPort, @NonNull String languageTag, @NonNull String layoutType)1745     private void addKeyboardLayoutAssociation(@NonNull String inputPort,
1746             @NonNull String languageTag, @NonNull String layoutType) {
1747         Objects.requireNonNull(inputPort);
1748         Objects.requireNonNull(languageTag);
1749         Objects.requireNonNull(layoutType);
1750 
1751         synchronized (mAssociationsLock) {
1752             mKeyboardLayoutAssociations.put(inputPort,
1753                     TextUtils.formatSimple("%s,%s", languageTag, layoutType));
1754         }
1755         mNative.changeKeyboardLayoutAssociation();
1756     }
1757 
removeKeyboardLayoutAssociation(@onNull String inputPort)1758     private void removeKeyboardLayoutAssociation(@NonNull String inputPort) {
1759         Objects.requireNonNull(inputPort);
1760         synchronized (mAssociationsLock) {
1761             mKeyboardLayoutAssociations.remove(inputPort);
1762         }
1763         mNative.changeKeyboardLayoutAssociation();
1764     }
1765 
1766     @Override // Binder call
getSensorList(int deviceId)1767     public InputSensorInfo[] getSensorList(int deviceId) {
1768         return mNative.getSensorList(deviceId);
1769     }
1770 
1771     @Override // Binder call
registerSensorListener(IInputSensorEventListener listener)1772     public boolean registerSensorListener(IInputSensorEventListener listener) {
1773         if (DEBUG) {
1774             Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid="
1775                     + Binder.getCallingPid());
1776         }
1777         Objects.requireNonNull(listener, "listener must not be null");
1778 
1779         synchronized (mSensorEventLock) {
1780             int callingPid = Binder.getCallingPid();
1781             if (mSensorEventListeners.get(callingPid) != null) {
1782                 Slog.e(TAG, "The calling process " + callingPid + " has already "
1783                         + "registered an InputSensorEventListener.");
1784                 return false;
1785             }
1786 
1787             SensorEventListenerRecord record =
1788                     new SensorEventListenerRecord(callingPid, listener);
1789             try {
1790                 IBinder binder = listener.asBinder();
1791                 binder.linkToDeath(record, 0);
1792             } catch (RemoteException ex) {
1793                 // give up
1794                 throw new RuntimeException(ex);
1795             }
1796 
1797             mSensorEventListeners.put(callingPid, record);
1798         }
1799         return true;
1800     }
1801 
1802     @Override // Binder call
unregisterSensorListener(IInputSensorEventListener listener)1803     public void unregisterSensorListener(IInputSensorEventListener listener) {
1804         if (DEBUG) {
1805             Slog.d(TAG, "unregisterSensorListener: listener=" + listener + " callingPid="
1806                     + Binder.getCallingPid());
1807         }
1808 
1809         Objects.requireNonNull(listener, "listener must not be null");
1810 
1811         synchronized (mSensorEventLock) {
1812             int callingPid = Binder.getCallingPid();
1813             if (mSensorEventListeners.get(callingPid) != null) {
1814                 SensorEventListenerRecord record = mSensorEventListeners.get(callingPid);
1815                 if (record.getListener().asBinder() != listener.asBinder()) {
1816                     throw new IllegalArgumentException("listener is not registered");
1817                 }
1818                 mSensorEventListeners.remove(callingPid);
1819             }
1820         }
1821     }
1822 
1823     @Override // Binder call
flushSensor(int deviceId, int sensorType)1824     public boolean flushSensor(int deviceId, int sensorType) {
1825         synchronized (mSensorEventLock) {
1826             int callingPid = Binder.getCallingPid();
1827             SensorEventListenerRecord listener = mSensorEventListeners.get(callingPid);
1828             if (listener != null) {
1829                 return mNative.flushSensor(deviceId, sensorType);
1830             }
1831             return false;
1832         }
1833     }
1834 
1835     @Override // Binder call
enableSensor(int deviceId, int sensorType, int samplingPeriodUs, int maxBatchReportLatencyUs)1836     public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
1837             int maxBatchReportLatencyUs) {
1838         synchronized (mInputDevicesLock) {
1839             return mNative.enableSensor(deviceId, sensorType, samplingPeriodUs,
1840                     maxBatchReportLatencyUs);
1841         }
1842     }
1843 
1844     @Override // Binder call
disableSensor(int deviceId, int sensorType)1845     public void disableSensor(int deviceId, int sensorType) {
1846         synchronized (mInputDevicesLock) {
1847             mNative.disableSensor(deviceId, sensorType);
1848         }
1849     }
1850 
1851     /**
1852      * LightSession represents a light session for lights manager.
1853      */
1854     private final class LightSession implements DeathRecipient {
1855         private final int mDeviceId;
1856         private final IBinder mToken;
1857         private final String mOpPkg;
1858         // The light ids and states that are requested by the light seesion
1859         private int[] mLightIds;
1860         private LightState[] mLightStates;
1861 
LightSession(int deviceId, String opPkg, IBinder token)1862         LightSession(int deviceId, String opPkg, IBinder token) {
1863             mDeviceId = deviceId;
1864             mOpPkg = opPkg;
1865             mToken = token;
1866         }
1867 
1868         @Override
binderDied()1869         public void binderDied() {
1870             if (DEBUG) {
1871                 Slog.d(TAG, "Light token died.");
1872             }
1873             synchronized (mLightLock) {
1874                 closeLightSession(mDeviceId, mToken);
1875                 mLightSessions.remove(mToken);
1876             }
1877         }
1878     }
1879 
1880     /**
1881      * Returns the lights available for apps to control on the specified input device.
1882      * Only lights that aren't reserved for system use are available to apps.
1883      */
1884     @Override // Binder call
getLights(int deviceId)1885     public List<Light> getLights(int deviceId) {
1886         return mNative.getLights(deviceId);
1887     }
1888 
1889     /**
1890      * Set specified light state with for a specific input device.
1891      */
setLightStateInternal(int deviceId, Light light, LightState lightState)1892     private void setLightStateInternal(int deviceId, Light light, LightState lightState) {
1893         Objects.requireNonNull(light, "light does not exist");
1894         if (DEBUG) {
1895             Slog.d(TAG, "setLightStateInternal device " + deviceId + " light " + light
1896                     + "lightState " + lightState);
1897         }
1898         if (light.getType() == Light.LIGHT_TYPE_PLAYER_ID) {
1899             mNative.setLightPlayerId(deviceId, light.getId(), lightState.getPlayerId());
1900         } else {
1901             // Set ARGB format color to input device light
1902             // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color
1903             mNative.setLightColor(deviceId, light.getId(), lightState.getColor());
1904         }
1905     }
1906 
1907     /**
1908      * Set multiple light states with multiple light ids for a specific input device.
1909      */
setLightStatesInternal(int deviceId, int[] lightIds, LightState[] lightStates)1910     private void setLightStatesInternal(int deviceId, int[] lightIds, LightState[] lightStates) {
1911         final List<Light> lights = mNative.getLights(deviceId);
1912         SparseArray<Light> lightArray = new SparseArray<>();
1913         for (int i = 0; i < lights.size(); i++) {
1914             lightArray.put(lights.get(i).getId(), lights.get(i));
1915         }
1916         for (int i = 0; i < lightIds.length; i++) {
1917             if (lightArray.contains(lightIds[i])) {
1918                 setLightStateInternal(deviceId, lightArray.get(lightIds[i]), lightStates[i]);
1919             }
1920         }
1921     }
1922 
1923     /**
1924      * Set states for multiple lights for an opened light session.
1925      */
1926     @Override
setLightStates(int deviceId, int[] lightIds, LightState[] lightStates, IBinder token)1927     public void setLightStates(int deviceId, int[] lightIds, LightState[] lightStates,
1928             IBinder token) {
1929         Preconditions.checkArgument(lightIds.length == lightStates.length,
1930                 "lights and light states are not same length");
1931         synchronized (mLightLock) {
1932             LightSession lightSession = mLightSessions.get(token);
1933             Preconditions.checkArgument(lightSession != null, "not registered");
1934             Preconditions.checkState(lightSession.mDeviceId == deviceId, "Incorrect device ID");
1935             lightSession.mLightIds = lightIds.clone();
1936             lightSession.mLightStates = lightStates.clone();
1937             if (DEBUG) {
1938                 Slog.d(TAG, "setLightStates for " + lightSession.mOpPkg + " device " + deviceId);
1939             }
1940         }
1941         setLightStatesInternal(deviceId, lightIds, lightStates);
1942     }
1943 
1944     @Override
getLightState(int deviceId, int lightId)1945     public @Nullable LightState getLightState(int deviceId, int lightId) {
1946         synchronized (mLightLock) {
1947             int color = mNative.getLightColor(deviceId, lightId);
1948             int playerId = mNative.getLightPlayerId(deviceId, lightId);
1949 
1950             return new LightState(color, playerId);
1951         }
1952     }
1953 
1954     @Override
openLightSession(int deviceId, String opPkg, IBinder token)1955     public void openLightSession(int deviceId, String opPkg, IBinder token) {
1956         Objects.requireNonNull(token);
1957         synchronized (mLightLock) {
1958             Preconditions.checkState(mLightSessions.get(token) == null, "already registered");
1959             LightSession lightSession = new LightSession(deviceId, opPkg, token);
1960             try {
1961                 token.linkToDeath(lightSession, 0);
1962             } catch (RemoteException ex) {
1963                 // give up
1964                 ex.rethrowAsRuntimeException();
1965             }
1966             mLightSessions.put(token, lightSession);
1967             if (DEBUG) {
1968                 Slog.d(TAG, "Open light session for " + opPkg + " device " + deviceId);
1969             }
1970         }
1971     }
1972 
1973     @Override
closeLightSession(int deviceId, IBinder token)1974     public void closeLightSession(int deviceId, IBinder token) {
1975         Objects.requireNonNull(token);
1976         synchronized (mLightLock) {
1977             LightSession lightSession = mLightSessions.get(token);
1978             Preconditions.checkState(lightSession != null, "not registered");
1979             // Turn off the lights that were previously requested by the session to be closed.
1980             Arrays.fill(lightSession.mLightStates, new LightState(0));
1981             setLightStatesInternal(deviceId, lightSession.mLightIds,
1982                     lightSession.mLightStates);
1983             mLightSessions.remove(token);
1984             // If any other session is still pending with light request, apply the first session's
1985             // request.
1986             if (!mLightSessions.isEmpty()) {
1987                 LightSession nextSession = mLightSessions.valueAt(0);
1988                 setLightStatesInternal(deviceId, nextSession.mLightIds, nextSession.mLightStates);
1989             }
1990         }
1991     }
1992 
1993     @Override
cancelCurrentTouch()1994     public void cancelCurrentTouch() {
1995         if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
1996                 "cancelCurrentTouch()")) {
1997             throw new SecurityException("Requires MONITOR_INPUT permission");
1998         }
1999 
2000         mNative.cancelCurrentTouch();
2001     }
2002 
2003     @Override
registerBatteryListener(int deviceId, IInputDeviceBatteryListener listener)2004     public void registerBatteryListener(int deviceId, IInputDeviceBatteryListener listener) {
2005         Objects.requireNonNull(listener);
2006         mBatteryController.registerBatteryListener(deviceId, listener, Binder.getCallingPid());
2007     }
2008 
2009     @Override
unregisterBatteryListener(int deviceId, IInputDeviceBatteryListener listener)2010     public void unregisterBatteryListener(int deviceId, IInputDeviceBatteryListener listener) {
2011         Objects.requireNonNull(listener);
2012         mBatteryController.unregisterBatteryListener(deviceId, listener, Binder.getCallingPid());
2013     }
2014 
2015     @EnforcePermission(Manifest.permission.BLUETOOTH)
2016     @Override
getInputDeviceBluetoothAddress(int deviceId)2017     public String getInputDeviceBluetoothAddress(int deviceId) {
2018         super.getInputDeviceBluetoothAddress_enforcePermission();
2019 
2020         final String address = mNative.getBluetoothAddress(deviceId);
2021         if (address == null) return null;
2022         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
2023             throw new IllegalStateException("The Bluetooth address of input device " + deviceId
2024                     + " should not be invalid: address=" + address);
2025         }
2026         return address;
2027     }
2028 
2029     @EnforcePermission(Manifest.permission.MONITOR_INPUT)
2030     @Override
pilferPointers(IBinder inputChannelToken)2031     public void pilferPointers(IBinder inputChannelToken) {
2032         super.pilferPointers_enforcePermission();
2033 
2034         Objects.requireNonNull(inputChannelToken);
2035         mNative.pilferPointers(inputChannelToken);
2036     }
2037 
2038     @Override
2039     @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT)
registerKeyboardBacklightListener(IKeyboardBacklightListener listener)2040     public void registerKeyboardBacklightListener(IKeyboardBacklightListener listener) {
2041         super.registerKeyboardBacklightListener_enforcePermission();
2042         Objects.requireNonNull(listener);
2043         mKeyboardBacklightController.registerKeyboardBacklightListener(listener,
2044                 Binder.getCallingPid());
2045     }
2046 
2047     @Override
2048     @EnforcePermission(Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT)
unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener)2049     public void unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener) {
2050         super.unregisterKeyboardBacklightListener_enforcePermission();
2051         Objects.requireNonNull(listener);
2052         mKeyboardBacklightController.unregisterKeyboardBacklightListener(listener,
2053                 Binder.getCallingPid());
2054     }
2055 
2056     @Override
getHostUsiVersionFromDisplayConfig(int displayId)2057     public HostUsiVersion getHostUsiVersionFromDisplayConfig(int displayId) {
2058         return mDisplayManagerInternal.getHostUsiVersion(displayId);
2059     }
2060 
2061     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2062     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2063         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2064         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
2065 
2066         ipw.println("INPUT MANAGER (dumpsys input)\n");
2067         String dumpStr = mNative.dump();
2068         if (dumpStr != null) {
2069             pw.println(dumpStr);
2070         }
2071 
2072         ipw.println("Input Manager Service (Java) State:");
2073         ipw.increaseIndent();
2074         dumpAssociations(ipw);
2075         dumpSpyWindowGestureMonitors(ipw);
2076         dumpDisplayInputPropertiesValues(ipw);
2077         mBatteryController.dump(ipw);
2078         mKeyboardBacklightController.dump(ipw);
2079         mKeyboardLedController.dump(ipw);
2080     }
2081 
dumpAssociations(IndentingPrintWriter pw)2082     private void dumpAssociations(IndentingPrintWriter pw) {
2083         if (!mStaticAssociations.isEmpty()) {
2084             pw.println("Static Associations:");
2085             mStaticAssociations.forEach((k, v) -> {
2086                 pw.print("  port: " + k);
2087                 pw.println("  display: " + v);
2088             });
2089         }
2090 
2091         synchronized (mAssociationsLock) {
2092             if (!mRuntimeAssociations.isEmpty()) {
2093                 pw.println("Runtime Associations:");
2094                 mRuntimeAssociations.forEach((k, v) -> {
2095                     pw.print("  port: " + k);
2096                     pw.println("  display: " + v);
2097                 });
2098             }
2099             if (!mUniqueIdAssociationsByPort.isEmpty()) {
2100                 pw.println("Unique Id Associations:");
2101                 mUniqueIdAssociationsByPort.forEach((k, v) -> {
2102                     pw.print("  port: " + k);
2103                     pw.println("  uniqueId: " + v);
2104                 });
2105             }
2106             if (!mUniqueIdAssociationsByDescriptor.isEmpty()) {
2107                 pw.println("Unique Id Associations:");
2108                 mUniqueIdAssociationsByDescriptor.forEach((k, v) -> {
2109                     pw.print("  descriptor: " + k);
2110                     pw.println("  uniqueId: " + v);
2111                 });
2112             }
2113             if (!mDeviceTypeAssociations.isEmpty()) {
2114                 pw.println("Type Associations:");
2115                 mDeviceTypeAssociations.forEach((k, v) -> {
2116                     pw.print("  port: " + k);
2117                     pw.println("  type: " + v);
2118                 });
2119             }
2120         }
2121     }
2122 
dumpSpyWindowGestureMonitors(IndentingPrintWriter pw)2123     private void dumpSpyWindowGestureMonitors(IndentingPrintWriter pw) {
2124         synchronized (mInputMonitors) {
2125             if (mInputMonitors.isEmpty()) return;
2126             pw.println("Gesture Monitors (implemented as spy windows):");
2127             int i = 0;
2128             for (final GestureMonitorSpyWindow monitor : mInputMonitors.values()) {
2129                 pw.append("  " + i++ + ": ").println(monitor.dump());
2130             }
2131         }
2132     }
2133 
dumpDisplayInputPropertiesValues(IndentingPrintWriter pw)2134     private void dumpDisplayInputPropertiesValues(IndentingPrintWriter pw) {
2135         synchronized (mAdditionalDisplayInputPropertiesLock) {
2136             pw.println("mAdditionalDisplayInputProperties:");
2137             pw.increaseIndent();
2138             try {
2139                 if (mAdditionalDisplayInputProperties.size() == 0) {
2140                     pw.println("<none>");
2141                     return;
2142                 }
2143                 for (int i = 0; i < mAdditionalDisplayInputProperties.size(); i++) {
2144                     pw.println("displayId: " + mAdditionalDisplayInputProperties.keyAt(i));
2145                     final AdditionalDisplayInputProperties properties =
2146                             mAdditionalDisplayInputProperties.valueAt(i);
2147                     pw.println("mousePointerAccelerationEnabled: "
2148                             + properties.mousePointerAccelerationEnabled);
2149                     pw.println("pointerIconVisible: " + properties.pointerIconVisible);
2150                 }
2151             } finally {
2152                 pw.decreaseIndent();
2153             }
2154         }
2155     }
checkCallingPermission(String permission, String func)2156     private boolean checkCallingPermission(String permission, String func) {
2157         return checkCallingPermission(permission, func, false /*checkInstrumentationSource*/);
2158     }
2159 
checkCallingPermission(String permission, String func, boolean checkInstrumentationSource)2160     private boolean checkCallingPermission(String permission, String func,
2161             boolean checkInstrumentationSource) {
2162         // Quick check: if the calling permission is me, it's all okay.
2163         if (Binder.getCallingPid() == Process.myPid()) {
2164             return true;
2165         }
2166 
2167         if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
2168             return true;
2169         }
2170 
2171         if (checkInstrumentationSource) {
2172             final ActivityManagerInternal ami =
2173                     LocalServices.getService(ActivityManagerInternal.class);
2174             Objects.requireNonNull(ami, "ActivityManagerInternal should not be null.");
2175             final int instrumentationUid = ami.getInstrumentationSourceUid(Binder.getCallingUid());
2176             if (instrumentationUid != Process.INVALID_UID) {
2177                 // Clear the calling identity when checking if the instrumentation source has
2178                 // permission because PackageManager will deny all permissions to some callers,
2179                 // such as instant apps.
2180                 final long token = Binder.clearCallingIdentity();
2181                 try {
2182                     if (mContext.checkPermission(permission, -1 /*pid*/, instrumentationUid)
2183                             == PackageManager.PERMISSION_GRANTED) {
2184                         return true;
2185                     }
2186                 } finally {
2187                     Binder.restoreCallingIdentity(token);
2188                 }
2189             }
2190         }
2191 
2192         String msg = "Permission Denial: " + func + " from pid="
2193                 + Binder.getCallingPid()
2194                 + ", uid=" + Binder.getCallingUid()
2195                 + " requires " + permission;
2196         Slog.w(TAG, msg);
2197         return false;
2198     }
2199 
2200     // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
2201     @Override
monitor()2202     public void monitor() {
2203         synchronized (mInputFilterLock) { }
2204         synchronized (mAssociationsLock) { /* Test if blocked by associations lock. */}
2205         synchronized (mLidSwitchLock) { /* Test if blocked by lid switch lock. */ }
2206         synchronized (mInputMonitors) { /* Test if blocked by input monitor lock. */ }
2207         synchronized (mAdditionalDisplayInputPropertiesLock) { /* Test if blocked by props lock */ }
2208         mBatteryController.monitor();
2209         mPointerIconCache.monitor();
2210         mNative.monitor();
2211     }
2212 
2213     // Native callback.
2214     @SuppressWarnings("unused")
notifyConfigurationChanged(long whenNanos)2215     private void notifyConfigurationChanged(long whenNanos) {
2216         mWindowManagerCallbacks.notifyConfigurationChanged();
2217     }
2218 
2219     // Native callback.
2220     @SuppressWarnings("unused")
notifyInputDevicesChanged(InputDevice[] inputDevices)2221     private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
2222         synchronized (mInputDevicesLock) {
2223             if (!mInputDevicesChangedPending) {
2224                 mInputDevicesChangedPending = true;
2225                 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
2226                         mInputDevices).sendToTarget();
2227             }
2228 
2229             mInputDevices = inputDevices;
2230         }
2231     }
2232 
2233     // Native callback.
2234     @SuppressWarnings("unused")
notifySwitch(long whenNanos, int switchValues, int switchMask)2235     private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
2236         if (DEBUG) {
2237             Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
2238                     + ", mask=" + Integer.toHexString(switchMask));
2239         }
2240 
2241         if ((switchMask & SW_LID_BIT) != 0) {
2242             final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
2243             synchronized (mLidSwitchLock) {
2244                 if (mSystemReady) {
2245                     for (int i = 0; i < mLidSwitchCallbacks.size(); i++) {
2246                         LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i);
2247                         callbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
2248                     }
2249                 }
2250             }
2251         }
2252 
2253         if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
2254             final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
2255             mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
2256             // Use SW_CAMERA_LENS_COVER code for camera privacy toggles
2257             setSensorPrivacy(Sensors.CAMERA, lensCovered);
2258         }
2259 
2260         if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
2261             mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
2262                     switchMask);
2263         }
2264 
2265         if ((switchMask & SW_TABLET_MODE_BIT) != 0) {
2266             SomeArgs args = SomeArgs.obtain();
2267             args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
2268             args.argi2 = (int) (whenNanos >> 32);
2269             args.arg1 = (switchValues & SW_TABLET_MODE_BIT) != 0;
2270             mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
2271                     args).sendToTarget();
2272         }
2273 
2274         if ((switchMask & SW_MUTE_DEVICE_BIT) != 0) {
2275             final boolean micMute = ((switchValues & SW_MUTE_DEVICE_BIT) != 0);
2276             AudioManager audioManager = mContext.getSystemService(AudioManager.class);
2277             audioManager.setMicrophoneMuteFromSwitch(micMute);
2278 
2279             setSensorPrivacy(Sensors.MICROPHONE, micMute);
2280         }
2281     }
2282 
2283     // Set the sensor privacy state based on the hardware toggles switch states
setSensorPrivacy(@ensorPrivacyManager.Sensors.Sensor int sensor, boolean enablePrivacy)2284     private void setSensorPrivacy(@SensorPrivacyManager.Sensors.Sensor int sensor,
2285             boolean enablePrivacy) {
2286         final SensorPrivacyManagerInternal sensorPrivacyManagerInternal =
2287                 LocalServices.getService(SensorPrivacyManagerInternal.class);
2288         sensorPrivacyManagerInternal.setPhysicalToggleSensorPrivacy(UserHandle.USER_CURRENT, sensor,
2289                 enablePrivacy);
2290     }
2291 
2292     // Native callback.
2293     @SuppressWarnings("unused")
notifyInputChannelBroken(IBinder token)2294     private void notifyInputChannelBroken(IBinder token) {
2295         synchronized (mInputMonitors) {
2296             if (mInputMonitors.containsKey(token)) {
2297                 removeSpyWindowGestureMonitor(token);
2298             }
2299         }
2300         mWindowManagerCallbacks.notifyInputChannelBroken(token);
2301     }
2302 
2303     // Native callback
2304     @SuppressWarnings("unused")
notifyFocusChanged(IBinder oldToken, IBinder newToken)2305     private void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
2306         mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
2307     }
2308 
2309     // Native callback
2310     @SuppressWarnings("unused")
notifyDropWindow(IBinder token, float x, float y)2311     private void notifyDropWindow(IBinder token, float x, float y) {
2312         mWindowManagerCallbacks.notifyDropWindow(token, x, y);
2313     }
2314 
2315     // Native callback.
2316     @SuppressWarnings("unused")
notifyNoFocusedWindowAnr(InputApplicationHandle inputApplicationHandle)2317     private void notifyNoFocusedWindowAnr(InputApplicationHandle inputApplicationHandle) {
2318         mWindowManagerCallbacks.notifyNoFocusedWindowAnr(inputApplicationHandle);
2319     }
2320 
2321     // Native callback
2322     @SuppressWarnings("unused")
notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid, String reason)2323     private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,
2324             String reason) {
2325         mWindowManagerCallbacks.notifyWindowUnresponsive(token,
2326                 isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);
2327     }
2328 
2329     // Native callback
2330     @SuppressWarnings("unused")
notifyWindowResponsive(IBinder token, int pid, boolean isPidValid)2331     private void notifyWindowResponsive(IBinder token, int pid, boolean isPidValid) {
2332         mWindowManagerCallbacks.notifyWindowResponsive(token,
2333                 isPidValid ? OptionalInt.of(pid) : OptionalInt.empty());
2334     }
2335 
2336     // Native callback.
2337     @SuppressWarnings("unused")
notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, float[] values)2338     private void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
2339             float[] values) {
2340         if (DEBUG) {
2341             Slog.d(TAG, "notifySensorEvent: deviceId=" + deviceId + " sensorType="
2342                     + sensorType + " values=" + Arrays.toString(values));
2343         }
2344         mSensorEventListenersToNotify.clear();
2345         final int numListeners;
2346         synchronized (mSensorEventLock) {
2347             numListeners = mSensorEventListeners.size();
2348             for (int i = 0; i < numListeners; i++) {
2349                 mSensorEventListenersToNotify.add(
2350                         mSensorEventListeners.valueAt(i));
2351             }
2352         }
2353         for (int i = 0; i < numListeners; i++) {
2354             mSensorEventListenersToNotify.get(i).notifySensorEvent(deviceId, sensorType,
2355                     accuracy, timestamp, values);
2356         }
2357         mSensorEventListenersToNotify.clear();
2358     }
2359 
2360     // Native callback.
2361     @SuppressWarnings("unused")
notifySensorAccuracy(int deviceId, int sensorType, int accuracy)2362     private void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
2363         mSensorAccuracyListenersToNotify.clear();
2364         final int numListeners;
2365         synchronized (mSensorEventLock) {
2366             numListeners = mSensorEventListeners.size();
2367             for (int i = 0; i < numListeners; i++) {
2368                 mSensorAccuracyListenersToNotify.add(mSensorEventListeners.valueAt(i));
2369             }
2370         }
2371         for (int i = 0; i < numListeners; i++) {
2372             mSensorAccuracyListenersToNotify.get(i).notifySensorAccuracy(
2373                     deviceId, sensorType, accuracy);
2374         }
2375         mSensorAccuracyListenersToNotify.clear();
2376     }
2377 
2378     // Native callback.
2379     @SuppressWarnings("unused")
filterInputEvent(InputEvent event, int policyFlags)2380     final boolean filterInputEvent(InputEvent event, int policyFlags) {
2381         synchronized (mInputFilterLock) {
2382             if (mInputFilter != null) {
2383                 try {
2384                     mInputFilter.filterInputEvent(event, policyFlags);
2385                 } catch (RemoteException e) {
2386                     /* ignore */
2387                 }
2388                 return false;
2389             }
2390         }
2391         event.recycle();
2392         return true;
2393     }
2394 
2395     // Native callback.
2396     @SuppressWarnings("unused")
interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)2397     private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
2398         synchronized (mFocusEventDebugViewLock) {
2399             if (mFocusEventDebugView != null) {
2400                 mFocusEventDebugView.reportKeyEvent(event);
2401             }
2402         }
2403         return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
2404     }
2405 
2406     // Native callback.
2407     @SuppressWarnings("unused")
interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action, long whenNanos, int policyFlags)2408     private int interceptMotionBeforeQueueingNonInteractive(int displayId,
2409             int source, int action, long whenNanos, int policyFlags) {
2410         return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
2411                 displayId, source, action, whenNanos, policyFlags);
2412     }
2413 
2414     // Native callback.
2415     @SuppressWarnings("unused")
interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags)2416     private long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) {
2417         return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
2418     }
2419 
2420     // Native callback.
2421     @SuppressWarnings("unused")
dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags)2422     private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) {
2423         return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
2424     }
2425 
2426     // Native callback.
2427     @SuppressWarnings("unused")
onPointerDownOutsideFocus(IBinder touchedToken)2428     private void onPointerDownOutsideFocus(IBinder touchedToken) {
2429         mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken);
2430     }
2431 
2432     // Native callback.
2433     @SuppressWarnings("unused")
getVirtualKeyQuietTimeMillis()2434     private int getVirtualKeyQuietTimeMillis() {
2435         return mContext.getResources().getInteger(
2436                 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
2437     }
2438 
2439     // Native callback.
2440     @SuppressWarnings("unused")
getExcludedDeviceNames()2441     private static String[] getExcludedDeviceNames() {
2442         List<String> names = new ArrayList<>();
2443         // Read partner-provided list of excluded input devices
2444         // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
2445         final File[] baseDirs = {
2446             Environment.getRootDirectory(),
2447             Environment.getVendorDirectory()
2448         };
2449         for (File baseDir: baseDirs) {
2450             File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH);
2451             try (InputStream stream = new FileInputStream(confFile)) {
2452                 names.addAll(ConfigurationProcessor.processExcludedDeviceNames(stream));
2453             } catch (FileNotFoundException e) {
2454                 // It's ok if the file does not exist.
2455             } catch (Exception e) {
2456                 Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e);
2457             }
2458         }
2459         return names.toArray(new String[0]);
2460     }
2461 
2462     // Native callback.
2463     @SuppressWarnings("unused")
isPerDisplayTouchModeEnabled()2464     private boolean isPerDisplayTouchModeEnabled() {
2465         return mContext.getResources().getBoolean(
2466                 com.android.internal.R.bool.config_perDisplayFocusEnabled);
2467     }
2468 
2469     // Native callback.
2470     @SuppressWarnings("unused")
notifyStylusGestureStarted(int deviceId, long eventTime)2471     private void notifyStylusGestureStarted(int deviceId, long eventTime) {
2472         mBatteryController.notifyStylusGestureStarted(deviceId, eventTime);
2473     }
2474 
2475     /**
2476      * Flatten a map into a string list, with value positioned directly next to the
2477      * key.
2478      * @return Flattened list
2479      */
flatten(@onNull Map<String, T> map)2480     private static <T> String[] flatten(@NonNull Map<String, T> map) {
2481         final List<String> list = new ArrayList<>(map.size() * 2);
2482         map.forEach((k, v)-> {
2483             list.add(k);
2484             list.add(v.toString());
2485         });
2486         return list.toArray(new String[0]);
2487     }
2488 
2489     /**
2490      * Ports are highly platform-specific, so allow these to be specified in the odm/vendor
2491      * directory.
2492      */
loadStaticInputPortAssociations()2493     private static Map<String, Integer> loadStaticInputPortAssociations() {
2494         File baseDir = Environment.getOdmDirectory();
2495         File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
2496 
2497         if (!confFile.exists()) {
2498             baseDir = Environment.getVendorDirectory();
2499             confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
2500         }
2501 
2502         try (final InputStream stream = new FileInputStream(confFile)) {
2503             return ConfigurationProcessor.processInputPortAssociations(stream);
2504         } catch (FileNotFoundException e) {
2505             // Most of the time, file will not exist, which is expected.
2506         } catch (Exception e) {
2507             Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e);
2508         }
2509 
2510         return new HashMap<>();
2511     }
2512 
2513     // Native callback
2514     @SuppressWarnings("unused")
getInputPortAssociations()2515     private String[] getInputPortAssociations() {
2516         final Map<String, Integer> associations = new HashMap<>(mStaticAssociations);
2517 
2518         // merge the runtime associations.
2519         synchronized (mAssociationsLock) {
2520             associations.putAll(mRuntimeAssociations);
2521         }
2522 
2523         return flatten(associations);
2524     }
2525 
2526     // Native callback
2527     @SuppressWarnings("unused")
getInputUniqueIdAssociationsByPort()2528     private String[] getInputUniqueIdAssociationsByPort() {
2529         final Map<String, String> associations;
2530         synchronized (mAssociationsLock) {
2531             associations = new HashMap<>(mUniqueIdAssociationsByPort);
2532         }
2533 
2534         return flatten(associations);
2535     }
2536 
2537     // Native callback
2538     @SuppressWarnings("unused")
getInputUniqueIdAssociationsByDescriptor()2539     private String[] getInputUniqueIdAssociationsByDescriptor() {
2540         final Map<String, String> associations;
2541         synchronized (mAssociationsLock) {
2542             associations = new HashMap<>(mUniqueIdAssociationsByDescriptor);
2543         }
2544 
2545         return flatten(associations);
2546     }
2547 
2548     // Native callback
2549     @SuppressWarnings("unused")
2550     @VisibleForTesting
getDeviceTypeAssociations()2551     String[] getDeviceTypeAssociations() {
2552         final Map<String, String> associations;
2553         synchronized (mAssociationsLock) {
2554             associations = new HashMap<>(mDeviceTypeAssociations);
2555         }
2556 
2557         return flatten(associations);
2558     }
2559 
2560     // Native callback
2561     @SuppressWarnings("unused")
2562     @VisibleForTesting
getKeyboardLayoutAssociations()2563     private String[] getKeyboardLayoutAssociations() {
2564         final Map<String, String> configs = new ArrayMap<>();
2565         synchronized (mAssociationsLock) {
2566             configs.putAll(mKeyboardLayoutAssociations);
2567         }
2568         return flatten(configs);
2569     }
2570 
2571     /**
2572      * Gets if an input device could dispatch to the given display".
2573      * @param deviceId The input device id.
2574      * @param displayId The specific display id.
2575      * @return True if the device could dispatch to the given display, false otherwise.
2576      */
canDispatchToDisplay(int deviceId, int displayId)2577     public boolean canDispatchToDisplay(int deviceId, int displayId) {
2578         return mNative.canDispatchToDisplay(deviceId, displayId);
2579     }
2580 
2581     // Native callback.
2582     @SuppressWarnings("unused")
getHoverTapTimeout()2583     private int getHoverTapTimeout() {
2584         return ViewConfiguration.getHoverTapTimeout();
2585     }
2586 
2587     // Native callback.
2588     @SuppressWarnings("unused")
getHoverTapSlop()2589     private int getHoverTapSlop() {
2590         return ViewConfiguration.getHoverTapSlop();
2591     }
2592 
2593     // Native callback.
2594     @SuppressWarnings("unused")
getDoubleTapTimeout()2595     private int getDoubleTapTimeout() {
2596         return ViewConfiguration.getDoubleTapTimeout();
2597     }
2598 
2599     // Native callback.
2600     @SuppressWarnings("unused")
getLongPressTimeout()2601     private int getLongPressTimeout() {
2602         return ViewConfiguration.getLongPressTimeout();
2603     }
2604 
2605     // Native callback.
2606     @SuppressWarnings("unused")
getPointerLayer()2607     private int getPointerLayer() {
2608         return mWindowManagerCallbacks.getPointerLayer();
2609     }
2610 
2611     // Native callback.
2612     @SuppressWarnings("unused")
getLoadedPointerIcon(int displayId, int type)2613     private @NonNull PointerIcon getLoadedPointerIcon(int displayId, int type) {
2614         return mPointerIconCache.getLoadedPointerIcon(displayId, type);
2615     }
2616 
2617     // Native callback.
2618     @SuppressWarnings("unused")
getParentSurfaceForPointers(int displayId)2619     private long getParentSurfaceForPointers(int displayId) {
2620         final SurfaceControl sc = mWindowManagerCallbacks.getParentSurfaceForPointers(displayId);
2621         if (sc == null) {
2622             return 0;
2623         }
2624         return sc.mNativeObject;
2625     }
2626 
2627     // Native callback.
2628     @SuppressWarnings("unused")
getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag, String layoutType)2629     private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier, String languageTag,
2630             String layoutType) {
2631         if (!mSystemReady) {
2632             return null;
2633         }
2634         return mKeyboardLayoutManager.getKeyboardLayoutOverlay(identifier, languageTag, layoutType);
2635     }
2636 
2637     @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS)
2638     @Override // Binder call
remapModifierKey(int fromKey, int toKey)2639     public void remapModifierKey(int fromKey, int toKey) {
2640         super.remapModifierKey_enforcePermission();
2641         mKeyRemapper.remapKey(fromKey, toKey);
2642     }
2643 
2644     @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS)
2645     @Override // Binder call
clearAllModifierKeyRemappings()2646     public void clearAllModifierKeyRemappings() {
2647         super.clearAllModifierKeyRemappings_enforcePermission();
2648         mKeyRemapper.clearAllKeyRemappings();
2649     }
2650 
2651     @EnforcePermission(Manifest.permission.REMAP_MODIFIER_KEYS)
2652     @Override // Binder call
getModifierKeyRemapping()2653     public Map<Integer, Integer> getModifierKeyRemapping() {
2654         super.getModifierKeyRemapping_enforcePermission();
2655         return mKeyRemapper.getKeyRemapping();
2656     }
2657 
2658     // Native callback.
2659     @SuppressWarnings("unused")
getDeviceAlias(String uniqueId)2660     private String getDeviceAlias(String uniqueId) {
2661         if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
2662             // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
2663             return null;
2664         }
2665         return null;
2666     }
2667 
2668     @Override
2669     @EnforcePermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE)
registerStickyModifierStateListener( @onNull IStickyModifierStateListener listener)2670     public void registerStickyModifierStateListener(
2671             @NonNull IStickyModifierStateListener listener) {
2672         super.registerStickyModifierStateListener_enforcePermission();
2673         Objects.requireNonNull(listener);
2674         mStickyModifierStateController.registerStickyModifierStateListener(listener,
2675                 Binder.getCallingPid());
2676     }
2677 
2678     @Override
2679     @EnforcePermission(Manifest.permission.MONITOR_STICKY_MODIFIER_STATE)
unregisterStickyModifierStateListener( @onNull IStickyModifierStateListener listener)2680     public void unregisterStickyModifierStateListener(
2681             @NonNull IStickyModifierStateListener listener) {
2682         super.unregisterStickyModifierStateListener_enforcePermission();
2683         Objects.requireNonNull(listener);
2684         mStickyModifierStateController.unregisterStickyModifierStateListener(listener,
2685                 Binder.getCallingPid());
2686     }
2687 
2688     // Native callback
2689     @SuppressWarnings("unused")
notifyStickyModifierStateChanged(int modifierState, int lockedModifierState)2690     void notifyStickyModifierStateChanged(int modifierState, int lockedModifierState) {
2691         mStickyModifierStateController.notifyStickyModifierStateChanged(modifierState,
2692                 lockedModifierState);
2693     }
2694 
2695     /**
2696      * Callback interface implemented by the Window Manager.
2697      */
2698     public interface WindowManagerCallbacks extends LidSwitchCallback {
2699         /**
2700          * This callback is invoked when the configuration changes.
2701          */
notifyConfigurationChanged()2702         void notifyConfigurationChanged();
2703 
2704         /**
2705          * This callback is invoked when the pointer location changes.
2706          */
notifyPointerLocationChanged(boolean pointerLocationEnabled)2707         void notifyPointerLocationChanged(boolean pointerLocationEnabled);
2708 
2709         /**
2710          * This callback is invoked when the camera lens cover switch changes state.
2711          * @param whenNanos the time when the change occurred
2712          * @param lensCovered true is the lens is covered
2713          */
notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered)2714         void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
2715 
2716         /**
2717          * This callback is invoked when an input channel is closed unexpectedly.
2718          * @param token the connection token of the broken channel
2719          */
notifyInputChannelBroken(IBinder token)2720         void notifyInputChannelBroken(IBinder token);
2721 
2722         /**
2723          * Notify the window manager about the focused application that does not have any focused
2724          * window and is unable to respond to focused input events.
2725          */
notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle)2726         void notifyNoFocusedWindowAnr(InputApplicationHandle applicationHandle);
2727 
2728         /**
2729          * Notify the window manager about a window that is unresponsive.
2730          *
2731          * @param token the token that can be used to look up the window
2732          * @param pid the pid of the window owner, if known
2733          * @param reason the reason why this connection is unresponsive
2734          */
notifyWindowUnresponsive(@onNull IBinder token, @NonNull OptionalInt pid, @NonNull String reason)2735         void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
2736                 @NonNull String reason);
2737 
2738         /**
2739          * Notify the window manager about a window that has become responsive.
2740          *
2741          * @param token the token that can be used to look up the window
2742          * @param pid the pid of the window owner, if known
2743          */
notifyWindowResponsive(@onNull IBinder token, @NonNull OptionalInt pid)2744         void notifyWindowResponsive(@NonNull IBinder token, @NonNull OptionalInt pid);
2745 
2746         /**
2747          * This callback is invoked when an event first arrives to InputDispatcher and before it is
2748          * placed onto InputDispatcher's queue. If this event is intercepted, it will never be
2749          * processed by InputDispacher.
2750          * @param event The key event that's arriving to InputDispatcher
2751          * @param policyFlags The policy flags
2752          * @return the flags that tell InputDispatcher how to handle the event (for example, whether
2753          * to pass it to the user)
2754          */
interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)2755         int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
2756 
2757         /**
2758          * Provides an opportunity for the window manager policy to intercept early motion event
2759          * processing when the device is in a non-interactive state since these events are normally
2760          * dropped.
2761          */
interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action, long whenNanos, int policyFlags)2762         int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action,
2763                 long whenNanos, int policyFlags);
2764 
2765         /**
2766          * This callback is invoked just before the key is about to be sent to an application.
2767          * This allows the policy to make some last minute decisions on whether to intercept this
2768          * key.
2769          * @param token the window token that's about to receive this event
2770          * @param event the key event that's being dispatched
2771          * @param policyFlags the policy flags
2772          * @return negative value if the key should be skipped (not sent to the app). 0 if the key
2773          * should proceed getting dispatched to the app. positive value to indicate the additional
2774          * time delay, in nanoseconds, to wait before sending this key to the app.
2775          */
interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags)2776         long interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags);
2777 
2778         /**
2779          * Dispatch unhandled key
2780          */
dispatchUnhandledKey(IBinder token, KeyEvent event, int policyFlags)2781         KeyEvent dispatchUnhandledKey(IBinder token, KeyEvent event, int policyFlags);
2782 
getPointerLayer()2783         int getPointerLayer();
2784 
getPointerDisplayId()2785         int getPointerDisplayId();
2786 
2787         /**
2788          * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event
2789          * occurred on a window that did not have focus.
2790          *
2791          * @param touchedToken The token for the window that received the input event.
2792          */
onPointerDownOutsideFocus(IBinder touchedToken)2793         void onPointerDownOutsideFocus(IBinder touchedToken);
2794 
2795         /**
2796          * Called when the focused window has changed.
2797          */
notifyFocusChanged(IBinder oldToken, IBinder newToken)2798         void notifyFocusChanged(IBinder oldToken, IBinder newToken);
2799 
2800         /**
2801          * Called when the drag over window has changed.
2802          */
notifyDropWindow(IBinder token, float x, float y)2803         void notifyDropWindow(IBinder token, float x, float y);
2804 
2805         /**
2806          * Get the {@link SurfaceControl} that should be the parent for the surfaces created for
2807          * pointers such as the mouse cursor and touch spots for the given display.
2808          */
getParentSurfaceForPointers(int displayId)2809         SurfaceControl getParentSurfaceForPointers(int displayId);
2810 
2811         /**
2812          * Create a {@link SurfaceControl} that can be configured to receive input over the entire
2813          * display to implement a gesture monitor. The surface will not have a graphical buffer.
2814          * @param name the name of the gesture monitor
2815          * @param displayId the display to create the window in
2816          * @return the SurfaceControl of the new layer container surface
2817          */
2818         @Nullable
createSurfaceForGestureMonitor(String name, int displayId)2819         SurfaceControl createSurfaceForGestureMonitor(String name, int displayId);
2820     }
2821 
2822     /**
2823      * Callback interface implemented by WiredAccessoryObserver.
2824      */
2825     public interface WiredAccessoryCallbacks {
2826         /**
2827          * Notifies WiredAccessoryObserver that input state for wired accessories has changed
2828          * @param whenNanos When the wired accessories changed
2829          * @param switchValues The state of the switches
2830          * @param switchMask The mask of switches that changed
2831          */
notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask)2832         void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
2833 
2834         /**
2835          * Notifies WiredAccessoryObserver that the system is now ready.
2836          */
systemReady()2837         void systemReady();
2838     }
2839 
2840     /**
2841      * Private handler for the input manager.
2842      */
2843     private final class InputManagerHandler extends Handler {
InputManagerHandler(Looper looper)2844         public InputManagerHandler(Looper looper) {
2845             super(looper, null, true /*async*/);
2846         }
2847 
2848         @Override
handleMessage(Message msg)2849         public void handleMessage(Message msg) {
2850             switch (msg.what) {
2851                 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
2852                     deliverInputDevicesChanged((InputDevice[])msg.obj);
2853                     break;
2854                 case MSG_RELOAD_DEVICE_ALIASES:
2855                     reloadDeviceAliases();
2856                     break;
2857                 case MSG_DELIVER_TABLET_MODE_CHANGED:
2858                     SomeArgs args = (SomeArgs) msg.obj;
2859                     long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32);
2860                     boolean inTabletMode = (boolean) args.arg1;
2861                     deliverTabletModeChanged(whenNanos, inTabletMode);
2862                     break;
2863             }
2864         }
2865     }
2866 
2867     /**
2868      * Hosting interface for input filters to call back into the input manager.
2869      */
2870     private final class InputFilterHost extends IInputFilterHost.Stub {
2871         @GuardedBy("mInputFilterLock")
2872         private boolean mDisconnected;
2873 
2874         @GuardedBy("mInputFilterLock")
disconnectLocked()2875         public void disconnectLocked() {
2876             mDisconnected = true;
2877         }
2878 
2879         @Override
sendInputEvent(InputEvent event, int policyFlags)2880         public void sendInputEvent(InputEvent event, int policyFlags) {
2881             if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
2882                     "sendInputEvent()")) {
2883                 throw new SecurityException(
2884                         "The INJECT_EVENTS permission is required for injecting input events.");
2885             }
2886             Objects.requireNonNull(event, "event must not be null");
2887 
2888             synchronized (mInputFilterLock) {
2889                 if (!mDisconnected) {
2890                     mNative.injectInputEvent(event, false /* injectIntoUid */, -1 /* uid */,
2891                             InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0 /* timeout */,
2892                             policyFlags | WindowManagerPolicy.FLAG_FILTERED);
2893                 }
2894             }
2895         }
2896     }
2897 
2898     /**
2899      * Interface for the system to handle request from InputMonitors.
2900      */
2901     private final class InputMonitorHost extends IInputMonitorHost.Stub {
2902         private final IBinder mInputChannelToken;
2903 
InputMonitorHost(IBinder inputChannelToken)2904         InputMonitorHost(IBinder inputChannelToken) {
2905             mInputChannelToken = inputChannelToken;
2906         }
2907 
2908         @Override
pilferPointers()2909         public void pilferPointers() {
2910             mNative.pilferPointers(mInputChannelToken);
2911         }
2912 
2913         @Override
dispose()2914         public void dispose() {
2915             removeSpyWindowGestureMonitor(mInputChannelToken);
2916         }
2917     }
2918 
2919     private final class InputDevicesChangedListenerRecord implements DeathRecipient {
2920         private final int mPid;
2921         private final IInputDevicesChangedListener mListener;
2922 
InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener)2923         public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
2924             mPid = pid;
2925             mListener = listener;
2926         }
2927 
2928         @Override
binderDied()2929         public void binderDied() {
2930             if (DEBUG) {
2931                 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
2932             }
2933             onInputDevicesChangedListenerDied(mPid);
2934         }
2935 
notifyInputDevicesChanged(int[] info)2936         public void notifyInputDevicesChanged(int[] info) {
2937             try {
2938                 mListener.onInputDevicesChanged(info);
2939             } catch (RemoteException ex) {
2940                 Slog.w(TAG, "Failed to notify process "
2941                         + mPid + " that input devices changed, assuming it died.", ex);
2942                 binderDied();
2943             }
2944         }
2945     }
2946 
2947     private final class TabletModeChangedListenerRecord implements DeathRecipient {
2948         private final int mPid;
2949         private final ITabletModeChangedListener mListener;
2950 
TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener)2951         public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) {
2952             mPid = pid;
2953             mListener = listener;
2954         }
2955 
2956         @Override
binderDied()2957         public void binderDied() {
2958             if (DEBUG) {
2959                 Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died.");
2960             }
2961             onTabletModeChangedListenerDied(mPid);
2962         }
2963 
notifyTabletModeChanged(long whenNanos, boolean inTabletMode)2964         public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) {
2965             try {
2966                 mListener.onTabletModeChanged(whenNanos, inTabletMode);
2967             } catch (RemoteException ex) {
2968                 Slog.w(TAG, "Failed to notify process " + mPid +
2969                         " that tablet mode changed, assuming it died.", ex);
2970                 binderDied();
2971             }
2972         }
2973     }
2974 
onSensorEventListenerDied(int pid)2975     private void onSensorEventListenerDied(int pid) {
2976         synchronized (mSensorEventLock) {
2977             mSensorEventListeners.remove(pid);
2978         }
2979     }
2980 
2981     private final class SensorEventListenerRecord implements DeathRecipient {
2982         private final int mPid;
2983         private final IInputSensorEventListener mListener;
2984 
SensorEventListenerRecord(int pid, IInputSensorEventListener listener)2985         SensorEventListenerRecord(int pid, IInputSensorEventListener listener) {
2986             mPid = pid;
2987             mListener = listener;
2988         }
2989 
2990         @Override
binderDied()2991         public void binderDied() {
2992             if (DEBUG) {
2993                 Slog.d(TAG, "Sensor event listener for pid " + mPid + " died.");
2994             }
2995             onSensorEventListenerDied(mPid);
2996         }
2997 
getListener()2998         public IInputSensorEventListener getListener() {
2999             return mListener;
3000         }
3001 
notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp, float[] values)3002         public void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
3003                 float[] values) {
3004             try {
3005                 mListener.onInputSensorChanged(deviceId, sensorType, accuracy, timestamp,
3006                         values);
3007             } catch (RemoteException ex) {
3008                 Slog.w(TAG, "Failed to notify process " + mPid
3009                         + " that sensor event notified, assuming it died.", ex);
3010                 binderDied();
3011             }
3012         }
3013 
notifySensorAccuracy(int deviceId, int sensorType, int accuracy)3014         public void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
3015             try {
3016                 mListener.onInputSensorAccuracyChanged(deviceId, sensorType, accuracy);
3017             } catch (RemoteException ex) {
3018                 Slog.w(TAG, "Failed to notify process " + mPid
3019                         + " that sensor accuracy notified, assuming it died.", ex);
3020                 binderDied();
3021             }
3022         }
3023     }
3024 
3025     private final class VibratorToken implements DeathRecipient {
3026         public final int mDeviceId;
3027         public final IBinder mToken;
3028         public final int mTokenValue;
3029 
3030         public boolean mVibrating;
3031 
VibratorToken(int deviceId, IBinder token, int tokenValue)3032         public VibratorToken(int deviceId, IBinder token, int tokenValue) {
3033             mDeviceId = deviceId;
3034             mToken = token;
3035             mTokenValue = tokenValue;
3036         }
3037 
3038         @Override
binderDied()3039         public void binderDied() {
3040             if (DEBUG) {
3041                 Slog.d(TAG, "Vibrator token died.");
3042             }
3043             onVibratorTokenDied(this);
3044         }
3045     }
3046 
3047     private final class LocalService extends InputManagerInternal {
3048         @Override
setDisplayViewports(List<DisplayViewport> viewports)3049         public void setDisplayViewports(List<DisplayViewport> viewports) {
3050             setDisplayViewportsInternal(viewports);
3051         }
3052 
3053         @Override
setInteractive(boolean interactive)3054         public void setInteractive(boolean interactive) {
3055             mNative.setInteractive(interactive);
3056             mBatteryController.onInteractiveChanged(interactive);
3057             mKeyboardBacklightController.onInteractiveChanged(interactive);
3058         }
3059 
3060         @Override
toggleCapsLock(int deviceId)3061         public void toggleCapsLock(int deviceId) {
3062             mNative.toggleCapsLock(deviceId);
3063         }
3064 
3065         @Override
setPulseGestureEnabled(boolean enabled)3066         public void setPulseGestureEnabled(boolean enabled) {
3067             if (mDoubleTouchGestureEnableFile != null) {
3068                 FileWriter writer = null;
3069                 try {
3070                     writer = new FileWriter(mDoubleTouchGestureEnableFile);
3071                     writer.write(enabled ? "1" : "0");
3072                 } catch (IOException e) {
3073                     Log.wtf(TAG, "Unable to setPulseGestureEnabled", e);
3074                 } finally {
3075                     IoUtils.closeQuietly(writer);
3076                 }
3077             }
3078         }
3079 
3080         @Override
transferTouchGesture(@onNull IBinder fromChannelToken, @NonNull IBinder toChannelToken)3081         public boolean transferTouchGesture(@NonNull IBinder fromChannelToken,
3082                 @NonNull IBinder toChannelToken) {
3083             return InputManagerService.this.transferTouchGesture(fromChannelToken, toChannelToken);
3084         }
3085 
3086         @Override
getCursorPosition(int displayId)3087         public PointF getCursorPosition(int displayId) {
3088             final float[] p = mNative.getMouseCursorPosition(displayId);
3089             if (p == null || p.length != 2) {
3090                 throw new IllegalStateException("Failed to get mouse cursor position");
3091             }
3092             return new PointF(p[0], p[1]);
3093         }
3094 
3095         @Override
setMousePointerAccelerationEnabled(boolean enabled, int displayId)3096         public void setMousePointerAccelerationEnabled(boolean enabled, int displayId) {
3097             InputManagerService.this.setMousePointerAccelerationEnabled(enabled, displayId);
3098         }
3099 
3100         @Override
setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible)3101         public void setDisplayEligibilityForPointerCapture(int displayId, boolean isEligible) {
3102             InputManagerService.this.setDisplayEligibilityForPointerCapture(displayId, isEligible);
3103         }
3104 
3105         @Override
setPointerIconVisible(boolean visible, int displayId)3106         public void setPointerIconVisible(boolean visible, int displayId) {
3107             InputManagerService.this.setPointerIconVisible(visible, displayId);
3108         }
3109 
3110         @Override
registerLidSwitchCallback(LidSwitchCallback callbacks)3111         public void registerLidSwitchCallback(LidSwitchCallback callbacks) {
3112             registerLidSwitchCallbackInternal(callbacks);
3113         }
3114 
3115         @Override
unregisterLidSwitchCallback(LidSwitchCallback callbacks)3116         public void unregisterLidSwitchCallback(LidSwitchCallback callbacks) {
3117             unregisterLidSwitchCallbackInternal(callbacks);
3118         }
3119 
3120         @Override
notifyInputMethodConnectionActive(boolean connectionIsActive)3121         public void notifyInputMethodConnectionActive(boolean connectionIsActive) {
3122             mNative.setInputMethodConnectionIsActive(connectionIsActive);
3123         }
3124 
3125         @Override
createInputChannel(String inputChannelName)3126         public InputChannel createInputChannel(String inputChannelName) {
3127             return InputManagerService.this.createInputChannel(inputChannelName);
3128         }
3129 
3130         @Override
pilferPointers(IBinder token)3131         public void pilferPointers(IBinder token) {
3132             mNative.pilferPointers(token);
3133         }
3134 
3135         @Override
onInputMethodSubtypeChangedForKeyboardLayoutMapping(@serIdInt int userId, @Nullable InputMethodSubtypeHandle subtypeHandle, @Nullable InputMethodSubtype subtype)3136         public void onInputMethodSubtypeChangedForKeyboardLayoutMapping(@UserIdInt int userId,
3137                 @Nullable InputMethodSubtypeHandle subtypeHandle,
3138                 @Nullable InputMethodSubtype subtype) {
3139             mKeyboardLayoutManager.onInputMethodSubtypeChanged(userId, subtypeHandle, subtype);
3140         }
3141 
3142         @Override
notifyUserActivity()3143         public void notifyUserActivity() {
3144             mKeyboardBacklightController.notifyUserActivity();
3145         }
3146 
3147         @Override
incrementKeyboardBacklight(int deviceId)3148         public void incrementKeyboardBacklight(int deviceId) {
3149             mKeyboardBacklightController.incrementKeyboardBacklight(deviceId);
3150         }
3151 
3152         @Override
decrementKeyboardBacklight(int deviceId)3153         public void decrementKeyboardBacklight(int deviceId) {
3154             mKeyboardBacklightController.decrementKeyboardBacklight(deviceId);
3155         }
3156 
3157         @Override
setTypeAssociation(@onNull String inputPort, @NonNull String type)3158         public void setTypeAssociation(@NonNull String inputPort, @NonNull String type) {
3159             setTypeAssociationInternal(inputPort, type);
3160         }
3161 
3162         @Override
unsetTypeAssociation(@onNull String inputPort)3163         public void unsetTypeAssociation(@NonNull String inputPort) {
3164             unsetTypeAssociationInternal(inputPort);
3165         }
3166 
3167         @Override
addKeyboardLayoutAssociation(@onNull String inputPort, @NonNull String languageTag, @NonNull String layoutType)3168         public void addKeyboardLayoutAssociation(@NonNull String inputPort,
3169                 @NonNull String languageTag, @NonNull String layoutType) {
3170             InputManagerService.this.addKeyboardLayoutAssociation(inputPort,
3171                     languageTag, layoutType);
3172         }
3173 
3174         @Override
removeKeyboardLayoutAssociation(@onNull String inputPort)3175         public void removeKeyboardLayoutAssociation(@NonNull String inputPort) {
3176             InputManagerService.this.removeKeyboardLayoutAssociation(inputPort);
3177         }
3178 
3179         @Override
setStylusButtonMotionEventsEnabled(boolean enabled)3180         public void setStylusButtonMotionEventsEnabled(boolean enabled) {
3181             mNative.setStylusButtonMotionEventsEnabled(enabled);
3182         }
3183 
3184         @Override
getLastUsedInputDeviceId()3185         public int getLastUsedInputDeviceId() {
3186             return mNative.getLastUsedInputDeviceId();
3187         }
3188     }
3189 
3190     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)3191     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
3192             String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
3193         new InputShellCommand().exec(this, in, out, err, args, callback, resultReceiver);
3194     }
3195 
3196     private static class AdditionalDisplayInputProperties {
3197 
3198         static final boolean DEFAULT_POINTER_ICON_VISIBLE = true;
3199         static final boolean DEFAULT_MOUSE_POINTER_ACCELERATION_ENABLED = true;
3200 
3201         /**
3202          * Whether to enable mouse pointer acceleration on this display. Note that this only affects
3203          * pointer movements from mice (that is, pointing devices which send relative motions,
3204          * including trackballs and pointing sticks), not from other pointer devices such as
3205          * touchpads and styluses.
3206          */
3207         public boolean mousePointerAccelerationEnabled;
3208 
3209         // Whether the pointer icon should be visible or hidden on this display.
3210         public boolean pointerIconVisible;
3211 
AdditionalDisplayInputProperties()3212         AdditionalDisplayInputProperties() {
3213             reset();
3214         }
3215 
allDefaults()3216         public boolean allDefaults() {
3217             return mousePointerAccelerationEnabled == DEFAULT_MOUSE_POINTER_ACCELERATION_ENABLED
3218                     && pointerIconVisible == DEFAULT_POINTER_ICON_VISIBLE;
3219         }
3220 
reset()3221         public void reset() {
3222             mousePointerAccelerationEnabled = DEFAULT_MOUSE_POINTER_ACCELERATION_ENABLED;
3223             pointerIconVisible = DEFAULT_POINTER_ICON_VISIBLE;
3224         }
3225     }
3226 
updateAdditionalDisplayInputProperties(int displayId, Consumer<AdditionalDisplayInputProperties> updater)3227     private void updateAdditionalDisplayInputProperties(int displayId,
3228             Consumer<AdditionalDisplayInputProperties> updater) {
3229         synchronized (mAdditionalDisplayInputPropertiesLock) {
3230             AdditionalDisplayInputProperties properties =
3231                     mAdditionalDisplayInputProperties.get(displayId);
3232             if (properties == null) {
3233                 properties = new AdditionalDisplayInputProperties();
3234                 mAdditionalDisplayInputProperties.put(displayId, properties);
3235             }
3236             final boolean oldPointerIconVisible = properties.pointerIconVisible;
3237             final boolean oldMouseAccelerationEnabled = properties.mousePointerAccelerationEnabled;
3238             updater.accept(properties);
3239             if (oldPointerIconVisible != properties.pointerIconVisible) {
3240                 mNative.setPointerIconVisibility(displayId, properties.pointerIconVisible);
3241             }
3242             if (oldMouseAccelerationEnabled != properties.mousePointerAccelerationEnabled) {
3243                 mNative.setMousePointerAccelerationEnabled(displayId,
3244                         properties.mousePointerAccelerationEnabled);
3245             }
3246             if (properties.allDefaults()) {
3247                 mAdditionalDisplayInputProperties.remove(displayId);
3248             }
3249         }
3250     }
3251 
updatePointerLocationEnabled(boolean enabled)3252     void updatePointerLocationEnabled(boolean enabled) {
3253         mWindowManagerCallbacks.notifyPointerLocationChanged(enabled);
3254     }
3255 
updateShowKeyPresses(boolean enabled)3256     void updateShowKeyPresses(boolean enabled) {
3257         if (mShowKeyPresses == enabled) {
3258             return;
3259         }
3260 
3261         mShowKeyPresses = enabled;
3262         updateFocusEventDebugViewEnabled();
3263 
3264         synchronized (mFocusEventDebugViewLock) {
3265             if (mFocusEventDebugView != null) {
3266                 mFocusEventDebugView.updateShowKeyPresses(enabled);
3267             }
3268         }
3269     }
3270 
updateShowRotaryInput(boolean enabled)3271     void updateShowRotaryInput(boolean enabled) {
3272         if (mShowRotaryInput == enabled) {
3273             return;
3274         }
3275 
3276         mShowRotaryInput = enabled;
3277         updateFocusEventDebugViewEnabled();
3278 
3279         synchronized (mFocusEventDebugViewLock) {
3280             if (mFocusEventDebugView != null) {
3281                 mFocusEventDebugView.updateShowRotaryInput(enabled);
3282             }
3283         }
3284     }
3285 
updateFocusEventDebugViewEnabled()3286     private void updateFocusEventDebugViewEnabled() {
3287         boolean enabled = mShowKeyPresses || mShowRotaryInput;
3288         FocusEventDebugView view;
3289         synchronized (mFocusEventDebugViewLock) {
3290             if (enabled == (mFocusEventDebugView != null)) {
3291                 return;
3292             }
3293             if (enabled) {
3294                 mFocusEventDebugView = new FocusEventDebugView(mContext, this);
3295                 view = mFocusEventDebugView;
3296             } else {
3297                 view = mFocusEventDebugView;
3298                 mFocusEventDebugView = null;
3299             }
3300         }
3301         Objects.requireNonNull(view);
3302 
3303         // Interact with WM outside the lock, since the lock is part of the input hotpath.
3304         final WindowManager wm =
3305                 Objects.requireNonNull(mContext.getSystemService(WindowManager.class));
3306         if (!enabled) {
3307             wm.removeView(view);
3308             return;
3309         }
3310 
3311         // TODO: Support multi display
3312         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
3313         lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
3314         lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
3315                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3316                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
3317         lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
3318         lp.setFitInsetsTypes(0);
3319         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
3320         lp.format = PixelFormat.TRANSLUCENT;
3321         lp.setTitle("FocusEventDebugView - display " + mContext.getDisplayId());
3322         lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
3323         wm.addView(view, lp);
3324     }
3325 
3326     /**
3327      * Sets Accessibility bounce keys threshold in milliseconds.
3328      */
setAccessibilityBounceKeysThreshold(int thresholdTimeMs)3329     public void setAccessibilityBounceKeysThreshold(int thresholdTimeMs) {
3330         mNative.setAccessibilityBounceKeysThreshold(thresholdTimeMs);
3331     }
3332 
3333     /**
3334      * Sets Accessibility slow keys threshold in milliseconds.
3335      */
setAccessibilitySlowKeysThreshold(int thresholdTimeMs)3336     public void setAccessibilitySlowKeysThreshold(int thresholdTimeMs) {
3337         mNative.setAccessibilitySlowKeysThreshold(thresholdTimeMs);
3338     }
3339 
3340     /**
3341      * Sets whether Accessibility sticky keys is enabled.
3342      */
setAccessibilityStickyKeysEnabled(boolean enabled)3343     public void setAccessibilityStickyKeysEnabled(boolean enabled) {
3344         mNative.setAccessibilityStickyKeysEnabled(enabled);
3345     }
3346 
setUseLargePointerIcons(boolean useLargeIcons)3347     void setUseLargePointerIcons(boolean useLargeIcons) {
3348         mPointerIconCache.setUseLargePointerIcons(useLargeIcons);
3349     }
3350 
setPointerFillStyle(@ointerIcon.PointerIconVectorStyleFill int fillStyle)3351     void setPointerFillStyle(@PointerIcon.PointerIconVectorStyleFill int fillStyle) {
3352         mPointerIconCache.setPointerFillStyle(fillStyle);
3353     }
3354 
setPointerScale(float scale)3355     void setPointerScale(float scale) {
3356         mPointerIconCache.setPointerScale(scale);
3357     }
3358 
3359     interface KeyboardBacklightControllerInterface {
incrementKeyboardBacklight(int deviceId)3360         default void incrementKeyboardBacklight(int deviceId) {}
decrementKeyboardBacklight(int deviceId)3361         default void decrementKeyboardBacklight(int deviceId) {}
registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid)3362         default void registerKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid)3363         default void unregisterKeyboardBacklightListener(IKeyboardBacklightListener l, int pid) {}
onInteractiveChanged(boolean isInteractive)3364         default void onInteractiveChanged(boolean isInteractive) {}
notifyUserActivity()3365         default void notifyUserActivity() {}
systemRunning()3366         default void systemRunning() {}
dump(PrintWriter pw)3367         default void dump(PrintWriter pw) {}
3368     }
3369 }
3370