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