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