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