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 android.annotation.NonNull; 20 import android.app.Notification; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.bluetooth.BluetoothAdapter; 24 import android.bluetooth.BluetoothDevice; 25 import android.content.BroadcastReceiver; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.ActivityInfo; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.PackageManager; 33 import android.content.pm.PackageManager.NameNotFoundException; 34 import android.content.pm.ResolveInfo; 35 import android.content.res.Resources; 36 import android.content.res.Resources.NotFoundException; 37 import android.content.res.TypedArray; 38 import android.content.res.XmlResourceParser; 39 import android.database.ContentObserver; 40 import android.hardware.display.DisplayManager; 41 import android.hardware.display.DisplayViewport; 42 import android.hardware.input.IInputDevicesChangedListener; 43 import android.hardware.input.IInputManager; 44 import android.hardware.input.ITabletModeChangedListener; 45 import android.hardware.input.InputDeviceIdentifier; 46 import android.hardware.input.InputManager; 47 import android.hardware.input.InputManagerInternal; 48 import android.hardware.input.KeyboardLayout; 49 import android.hardware.input.TouchCalibration; 50 import android.media.AudioManager; 51 import android.os.Binder; 52 import android.os.Bundle; 53 import android.os.Environment; 54 import android.os.Handler; 55 import android.os.IBinder; 56 import android.os.LocaleList; 57 import android.os.Looper; 58 import android.os.Message; 59 import android.os.MessageQueue; 60 import android.os.Process; 61 import android.os.RemoteException; 62 import android.os.UserHandle; 63 import android.provider.DeviceConfig; 64 import android.provider.Settings; 65 import android.provider.Settings.SettingNotFoundException; 66 import android.text.TextUtils; 67 import android.util.Log; 68 import android.util.Pair; 69 import android.util.Slog; 70 import android.util.SparseArray; 71 import android.view.Display; 72 import android.view.IInputFilter; 73 import android.view.IInputFilterHost; 74 import android.view.IInputMonitorHost; 75 import android.view.IWindow; 76 import android.view.InputApplicationHandle; 77 import android.view.InputChannel; 78 import android.view.InputDevice; 79 import android.view.InputEvent; 80 import android.view.InputMonitor; 81 import android.view.InputWindowHandle; 82 import android.view.KeyEvent; 83 import android.view.PointerIcon; 84 import android.view.Surface; 85 import android.view.ViewConfiguration; 86 import android.widget.Toast; 87 88 import com.android.internal.R; 89 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 90 import com.android.internal.notification.SystemNotificationChannels; 91 import com.android.internal.os.SomeArgs; 92 import com.android.internal.util.DumpUtils; 93 import com.android.internal.util.Preconditions; 94 import com.android.internal.util.XmlUtils; 95 import com.android.server.DisplayThread; 96 import com.android.server.LocalServices; 97 import com.android.server.Watchdog; 98 import com.android.server.policy.WindowManagerPolicy; 99 100 import libcore.io.IoUtils; 101 import libcore.io.Streams; 102 103 import java.io.File; 104 import java.io.FileDescriptor; 105 import java.io.FileInputStream; 106 import java.io.FileNotFoundException; 107 import java.io.FileWriter; 108 import java.io.IOException; 109 import java.io.InputStream; 110 import java.io.InputStreamReader; 111 import java.io.PrintWriter; 112 import java.util.ArrayList; 113 import java.util.Collections; 114 import java.util.HashMap; 115 import java.util.HashSet; 116 import java.util.List; 117 import java.util.Locale; 118 import java.util.Objects; 119 120 /* 121 * Wraps the C++ InputManager and provides its callbacks. 122 */ 123 public class InputManagerService extends IInputManager.Stub 124 implements Watchdog.Monitor { 125 static final String TAG = "InputManager"; 126 static final boolean DEBUG = false; 127 128 private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml"; 129 private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml"; 130 131 // Feature flag name for the deep press feature 132 private static final String DEEP_PRESS_ENABLED = "deep_press_enabled"; 133 134 private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1; 135 private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2; 136 private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3; 137 private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4; 138 private static final int MSG_RELOAD_DEVICE_ALIASES = 5; 139 private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6; 140 141 // Pointer to native input manager service object. 142 private final long mPtr; 143 144 private final Context mContext; 145 private final InputManagerHandler mHandler; 146 147 // Context cache used for loading pointer resources. 148 private Context mDisplayContext; 149 150 private final File mDoubleTouchGestureEnableFile; 151 152 private WindowManagerCallbacks mWindowManagerCallbacks; 153 private WiredAccessoryCallbacks mWiredAccessoryCallbacks; 154 private boolean mSystemReady; 155 private NotificationManager mNotificationManager; 156 157 private final Object mTabletModeLock = new Object(); 158 // List of currently registered tablet mode changed listeners by process id 159 private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners = 160 new SparseArray<>(); // guarded by mTabletModeLock 161 private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify = 162 new ArrayList<>(); 163 164 // Persistent data store. Must be locked each time during use. 165 private final PersistentDataStore mDataStore = new PersistentDataStore(); 166 167 // List of currently registered input devices changed listeners by process id. 168 private Object mInputDevicesLock = new Object(); 169 private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock 170 private InputDevice[] mInputDevices = new InputDevice[0]; 171 private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners = 172 new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock 173 private final ArrayList<InputDevicesChangedListenerRecord> 174 mTempInputDevicesChangedListenersToNotify = 175 new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only 176 private final ArrayList<InputDevice> 177 mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only 178 private boolean mKeyboardLayoutNotificationShown; 179 private PendingIntent mKeyboardLayoutIntent; 180 private Toast mSwitchedKeyboardLayoutToast; 181 182 // State for vibrator tokens. 183 private Object mVibratorLock = new Object(); 184 private HashMap<IBinder, VibratorToken> mVibratorTokens = 185 new HashMap<IBinder, VibratorToken>(); 186 private int mNextVibratorTokenValue; 187 188 // State for the currently installed input filter. 189 final Object mInputFilterLock = new Object(); 190 IInputFilter mInputFilter; // guarded by mInputFilterLock 191 InputFilterHost mInputFilterHost; // guarded by mInputFilterLock 192 193 private IWindow mFocusedWindow; 194 private boolean mFocusedWindowHasCapture; 195 nativeInit(InputManagerService service, Context context, MessageQueue messageQueue)196 private static native long nativeInit(InputManagerService service, 197 Context context, MessageQueue messageQueue); nativeStart(long ptr)198 private static native void nativeStart(long ptr); nativeSetDisplayViewports(long ptr, DisplayViewport[] viewports)199 private static native void nativeSetDisplayViewports(long ptr, 200 DisplayViewport[] viewports); 201 nativeGetScanCodeState(long ptr, int deviceId, int sourceMask, int scanCode)202 private static native int nativeGetScanCodeState(long ptr, 203 int deviceId, int sourceMask, int scanCode); nativeGetKeyCodeState(long ptr, int deviceId, int sourceMask, int keyCode)204 private static native int nativeGetKeyCodeState(long ptr, 205 int deviceId, int sourceMask, int keyCode); nativeGetSwitchState(long ptr, int deviceId, int sourceMask, int sw)206 private static native int nativeGetSwitchState(long ptr, 207 int deviceId, int sourceMask, int sw); nativeHasKeys(long ptr, int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists)208 private static native boolean nativeHasKeys(long ptr, 209 int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists); nativeRegisterInputChannel(long ptr, InputChannel inputChannel, int displayId)210 private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel, 211 int displayId); nativeRegisterInputMonitor(long ptr, InputChannel inputChannel, int displayId, boolean isGestureMonitor)212 private static native void nativeRegisterInputMonitor(long ptr, InputChannel inputChannel, 213 int displayId, boolean isGestureMonitor); nativeUnregisterInputChannel(long ptr, InputChannel inputChannel)214 private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel); nativePilferPointers(long ptr, IBinder token)215 private static native void nativePilferPointers(long ptr, IBinder token); nativeSetInputFilterEnabled(long ptr, boolean enable)216 private static native void nativeSetInputFilterEnabled(long ptr, boolean enable); nativeInjectInputEvent(long ptr, InputEvent event, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags)217 private static native int nativeInjectInputEvent(long ptr, InputEvent event, 218 int injectorPid, int injectorUid, int syncMode, int timeoutMillis, 219 int policyFlags); nativeToggleCapsLock(long ptr, int deviceId)220 private static native void nativeToggleCapsLock(long ptr, int deviceId); nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles, int displayId)221 private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles, 222 int displayId); nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen)223 private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen); nativeSetSystemUiVisibility(long ptr, int visibility)224 private static native void nativeSetSystemUiVisibility(long ptr, int visibility); nativeSetFocusedApplication(long ptr, int displayId, InputApplicationHandle application)225 private static native void nativeSetFocusedApplication(long ptr, 226 int displayId, InputApplicationHandle application); nativeSetFocusedDisplay(long ptr, int displayId)227 private static native void nativeSetFocusedDisplay(long ptr, int displayId); nativeTransferTouchFocus(long ptr, InputChannel fromChannel, InputChannel toChannel)228 private static native boolean nativeTransferTouchFocus(long ptr, 229 InputChannel fromChannel, InputChannel toChannel); nativeSetPointerSpeed(long ptr, int speed)230 private static native void nativeSetPointerSpeed(long ptr, int speed); nativeSetShowTouches(long ptr, boolean enabled)231 private static native void nativeSetShowTouches(long ptr, boolean enabled); nativeSetInteractive(long ptr, boolean interactive)232 private static native void nativeSetInteractive(long ptr, boolean interactive); nativeReloadCalibration(long ptr)233 private static native void nativeReloadCalibration(long ptr); nativeVibrate(long ptr, int deviceId, long[] pattern, int repeat, int token)234 private static native void nativeVibrate(long ptr, int deviceId, long[] pattern, 235 int repeat, int token); nativeCancelVibrate(long ptr, int deviceId, int token)236 private static native void nativeCancelVibrate(long ptr, int deviceId, int token); nativeReloadKeyboardLayouts(long ptr)237 private static native void nativeReloadKeyboardLayouts(long ptr); nativeReloadDeviceAliases(long ptr)238 private static native void nativeReloadDeviceAliases(long ptr); nativeDump(long ptr)239 private static native String nativeDump(long ptr); nativeMonitor(long ptr)240 private static native void nativeMonitor(long ptr); nativeIsInputDeviceEnabled(long ptr, int deviceId)241 private static native boolean nativeIsInputDeviceEnabled(long ptr, int deviceId); nativeEnableInputDevice(long ptr, int deviceId)242 private static native void nativeEnableInputDevice(long ptr, int deviceId); nativeDisableInputDevice(long ptr, int deviceId)243 private static native void nativeDisableInputDevice(long ptr, int deviceId); nativeSetPointerIconType(long ptr, int iconId)244 private static native void nativeSetPointerIconType(long ptr, int iconId); nativeReloadPointerIcons(long ptr)245 private static native void nativeReloadPointerIcons(long ptr); nativeSetCustomPointerIcon(long ptr, PointerIcon icon)246 private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon); nativeSetPointerCapture(long ptr, boolean detached)247 private static native void nativeSetPointerCapture(long ptr, boolean detached); nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId)248 private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId); nativeSetMotionClassifierEnabled(long ptr, boolean enabled)249 private static native void nativeSetMotionClassifierEnabled(long ptr, boolean enabled); 250 251 // Input event injection constants defined in InputDispatcher.h. 252 private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0; 253 private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1; 254 private static final int INPUT_EVENT_INJECTION_FAILED = 2; 255 private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3; 256 257 // Maximum number of milliseconds to wait for input event injection. 258 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000; 259 260 // Key states (may be returned by queries about the current state of a 261 // particular key code, scan code or switch). 262 263 /** The key state is unknown or the requested key itself is not supported. */ 264 public static final int KEY_STATE_UNKNOWN = -1; 265 266 /** The key is up. /*/ 267 public static final int KEY_STATE_UP = 0; 268 269 /** The key is down. */ 270 public static final int KEY_STATE_DOWN = 1; 271 272 /** The key is down but is a virtual key press that is being emulated by the system. */ 273 public static final int KEY_STATE_VIRTUAL = 2; 274 275 /** Scan code: Mouse / trackball button. */ 276 public static final int BTN_MOUSE = 0x110; 277 278 // Switch code values must match bionic/libc/kernel/common/linux/input.h 279 /** Switch code: Lid switch. When set, lid is shut. */ 280 public static final int SW_LID = 0x00; 281 282 /** Switch code: Tablet mode switch. 283 * When set, the device is in tablet mode (i.e. no keyboard is connected). 284 */ 285 public static final int SW_TABLET_MODE = 0x01; 286 287 /** Switch code: Keypad slide. When set, keyboard is exposed. */ 288 public static final int SW_KEYPAD_SLIDE = 0x0a; 289 290 /** Switch code: Headphone. When set, headphone is inserted. */ 291 public static final int SW_HEADPHONE_INSERT = 0x02; 292 293 /** Switch code: Microphone. When set, microphone is inserted. */ 294 public static final int SW_MICROPHONE_INSERT = 0x04; 295 296 /** Switch code: Line out. When set, Line out (hi-Z) is inserted. */ 297 public static final int SW_LINEOUT_INSERT = 0x06; 298 299 /** Switch code: Headphone/Microphone Jack. When set, something is inserted. */ 300 public static final int SW_JACK_PHYSICAL_INSERT = 0x07; 301 302 /** Switch code: Camera lens cover. When set the lens is covered. */ 303 public static final int SW_CAMERA_LENS_COVER = 0x09; 304 305 /** Switch code: Microphone. When set it is off. */ 306 public static final int SW_MUTE_DEVICE = 0x0e; 307 308 public static final int SW_LID_BIT = 1 << SW_LID; 309 public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE; 310 public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE; 311 public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT; 312 public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT; 313 public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT; 314 public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT; 315 public static final int SW_JACK_BITS = 316 SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT; 317 public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER; 318 public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE; 319 320 /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ 321 final boolean mUseDevInputEventForAudioJack; 322 InputManagerService(Context context)323 public InputManagerService(Context context) { 324 this.mContext = context; 325 this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); 326 327 mUseDevInputEventForAudioJack = 328 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); 329 Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" 330 + mUseDevInputEventForAudioJack); 331 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); 332 333 String doubleTouchGestureEnablePath = context.getResources().getString( 334 R.string.config_doubleTouchGestureEnableFile); 335 mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : 336 new File(doubleTouchGestureEnablePath); 337 338 LocalServices.addService(InputManagerInternal.class, new LocalService()); 339 } 340 setWindowManagerCallbacks(WindowManagerCallbacks callbacks)341 public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) { 342 mWindowManagerCallbacks = callbacks; 343 } 344 setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks)345 public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) { 346 mWiredAccessoryCallbacks = callbacks; 347 } 348 start()349 public void start() { 350 Slog.i(TAG, "Starting input manager"); 351 nativeStart(mPtr); 352 353 // Add ourself to the Watchdog monitors. 354 Watchdog.getInstance().addMonitor(this); 355 356 registerPointerSpeedSettingObserver(); 357 registerShowTouchesSettingObserver(); 358 registerAccessibilityLargePointerSettingObserver(); 359 registerLongPressTimeoutObserver(); 360 361 mContext.registerReceiver(new BroadcastReceiver() { 362 @Override 363 public void onReceive(Context context, Intent intent) { 364 updatePointerSpeedFromSettings(); 365 updateShowTouchesFromSettings(); 366 updateAccessibilityLargePointerFromSettings(); 367 updateDeepPressStatusFromSettings("user switched"); 368 } 369 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); 370 371 updatePointerSpeedFromSettings(); 372 updateShowTouchesFromSettings(); 373 updateAccessibilityLargePointerFromSettings(); 374 updateDeepPressStatusFromSettings("just booted"); 375 } 376 377 // TODO(BT) Pass in parameter for bluetooth system systemRunning()378 public void systemRunning() { 379 if (DEBUG) { 380 Slog.d(TAG, "System ready."); 381 } 382 mNotificationManager = (NotificationManager)mContext.getSystemService( 383 Context.NOTIFICATION_SERVICE); 384 mSystemReady = true; 385 386 IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); 387 filter.addAction(Intent.ACTION_PACKAGE_REMOVED); 388 filter.addAction(Intent.ACTION_PACKAGE_CHANGED); 389 filter.addAction(Intent.ACTION_PACKAGE_REPLACED); 390 filter.addDataScheme("package"); 391 mContext.registerReceiver(new BroadcastReceiver() { 392 @Override 393 public void onReceive(Context context, Intent intent) { 394 updateKeyboardLayouts(); 395 } 396 }, filter, null, mHandler); 397 398 filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED); 399 mContext.registerReceiver(new BroadcastReceiver() { 400 @Override 401 public void onReceive(Context context, Intent intent) { 402 reloadDeviceAliases(); 403 } 404 }, filter, null, mHandler); 405 406 mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES); 407 mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS); 408 409 if (mWiredAccessoryCallbacks != null) { 410 mWiredAccessoryCallbacks.systemReady(); 411 } 412 } 413 reloadKeyboardLayouts()414 private void reloadKeyboardLayouts() { 415 if (DEBUG) { 416 Slog.d(TAG, "Reloading keyboard layouts."); 417 } 418 nativeReloadKeyboardLayouts(mPtr); 419 } 420 reloadDeviceAliases()421 private void reloadDeviceAliases() { 422 if (DEBUG) { 423 Slog.d(TAG, "Reloading device names."); 424 } 425 nativeReloadDeviceAliases(mPtr); 426 } 427 setDisplayViewportsInternal(List<DisplayViewport> viewports)428 private void setDisplayViewportsInternal(List<DisplayViewport> viewports) { 429 nativeSetDisplayViewports(mPtr, viewports.toArray(new DisplayViewport[0])); 430 } 431 432 /** 433 * Gets the current state of a key or button by key code. 434 * @param deviceId The input device id, or -1 to consult all devices. 435 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 436 * consider all input sources. An input device is consulted if at least one of its 437 * non-class input source bits matches the specified source mask. 438 * @param keyCode The key code to check. 439 * @return The key state. 440 */ getKeyCodeState(int deviceId, int sourceMask, int keyCode)441 public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) { 442 return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode); 443 } 444 445 /** 446 * Gets the current state of a key or button by scan code. 447 * @param deviceId The input device id, or -1 to consult all devices. 448 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 449 * consider all input sources. An input device is consulted if at least one of its 450 * non-class input source bits matches the specified source mask. 451 * @param scanCode The scan code to check. 452 * @return The key state. 453 */ getScanCodeState(int deviceId, int sourceMask, int scanCode)454 public int getScanCodeState(int deviceId, int sourceMask, int scanCode) { 455 return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode); 456 } 457 458 /** 459 * Gets the current state of a switch by switch code. 460 * @param deviceId The input device id, or -1 to consult all devices. 461 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 462 * consider all input sources. An input device is consulted if at least one of its 463 * non-class input source bits matches the specified source mask. 464 * @param switchCode The switch code to check. 465 * @return The switch state. 466 */ getSwitchState(int deviceId, int sourceMask, int switchCode)467 public int getSwitchState(int deviceId, int sourceMask, int switchCode) { 468 return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode); 469 } 470 471 /** 472 * Determines whether the specified key codes are supported by a particular device. 473 * @param deviceId The input device id, or -1 to consult all devices. 474 * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to 475 * consider all input sources. An input device is consulted if at least one of its 476 * non-class input source bits matches the specified source mask. 477 * @param keyCodes The array of key codes to check. 478 * @param keyExists An array at least as large as keyCodes whose entries will be set 479 * to true or false based on the presence or absence of support for the corresponding 480 * key codes. 481 * @return True if the lookup was successful, false otherwise. 482 */ 483 @Override // Binder call hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists)484 public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) { 485 if (keyCodes == null) { 486 throw new IllegalArgumentException("keyCodes must not be null."); 487 } 488 if (keyExists == null || keyExists.length < keyCodes.length) { 489 throw new IllegalArgumentException("keyExists must not be null and must be at " 490 + "least as large as keyCodes."); 491 } 492 493 return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists); 494 } 495 496 /** 497 * Creates an input channel that will receive all input from the input dispatcher. 498 * @param inputChannelName The input channel name. 499 * @param displayId Target display id. 500 * @return The input channel. 501 */ monitorInput(String inputChannelName, int displayId)502 public InputChannel monitorInput(String inputChannelName, int displayId) { 503 if (inputChannelName == null) { 504 throw new IllegalArgumentException("inputChannelName must not be null."); 505 } 506 507 if (displayId < Display.DEFAULT_DISPLAY) { 508 throw new IllegalArgumentException("displayId must >= 0."); 509 } 510 511 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName); 512 // Give the output channel a token just for identity purposes. 513 inputChannels[0].setToken(new Binder()); 514 nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId, false /*isGestureMonitor*/); 515 inputChannels[0].dispose(); // don't need to retain the Java object reference 516 return inputChannels[1]; 517 } 518 519 /** 520 * Creates an input monitor that will receive pointer events for the purposes of system-wide 521 * gesture interpretation. 522 * 523 * @param inputChannelName The input channel name. 524 * @param displayId Target display id. 525 * @return The input channel. 526 */ 527 @Override // Binder call monitorGestureInput(String inputChannelName, int displayId)528 public InputMonitor monitorGestureInput(String inputChannelName, int displayId) { 529 if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT, 530 "monitorInputRegion()")) { 531 throw new SecurityException("Requires MONITOR_INPUT permission"); 532 } 533 534 Objects.requireNonNull(inputChannelName, "inputChannelName must not be null."); 535 536 if (displayId < Display.DEFAULT_DISPLAY) { 537 throw new IllegalArgumentException("displayId must >= 0."); 538 } 539 540 541 final long ident = Binder.clearCallingIdentity(); 542 try { 543 InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName); 544 InputMonitorHost host = new InputMonitorHost(inputChannels[0]); 545 inputChannels[0].setToken(host.asBinder()); 546 nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId, 547 true /*isGestureMonitor*/); 548 return new InputMonitor(inputChannelName, inputChannels[1], host); 549 } finally { 550 Binder.restoreCallingIdentity(ident); 551 } 552 } 553 554 /** 555 * Registers an input channel so that it can be used as an input event target. 556 * @param inputChannel The input channel to register. 557 * @param inputWindowHandle The handle of the input window associated with the 558 * input channel, or null if none. 559 */ registerInputChannel(InputChannel inputChannel, IBinder token)560 public void registerInputChannel(InputChannel inputChannel, IBinder token) { 561 if (inputChannel == null) { 562 throw new IllegalArgumentException("inputChannel must not be null."); 563 } 564 565 if (token == null) { 566 token = new Binder(); 567 } 568 inputChannel.setToken(token); 569 570 nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY); 571 } 572 573 /** 574 * Unregisters an input channel. 575 * @param inputChannel The input channel to unregister. 576 */ unregisterInputChannel(InputChannel inputChannel)577 public void unregisterInputChannel(InputChannel inputChannel) { 578 if (inputChannel == null) { 579 throw new IllegalArgumentException("inputChannel must not be null."); 580 } 581 582 nativeUnregisterInputChannel(mPtr, inputChannel); 583 } 584 585 /** 586 * Sets an input filter that will receive all input events before they are dispatched. 587 * The input filter may then reinterpret input events or inject new ones. 588 * 589 * To ensure consistency, the input dispatcher automatically drops all events 590 * in progress whenever an input filter is installed or uninstalled. After an input 591 * filter is uninstalled, it can no longer send input events unless it is reinstalled. 592 * Any events it attempts to send after it has been uninstalled will be dropped. 593 * 594 * @param filter The input filter, or null to remove the current filter. 595 */ setInputFilter(IInputFilter filter)596 public void setInputFilter(IInputFilter filter) { 597 synchronized (mInputFilterLock) { 598 final IInputFilter oldFilter = mInputFilter; 599 if (oldFilter == filter) { 600 return; // nothing to do 601 } 602 603 if (oldFilter != null) { 604 mInputFilter = null; 605 mInputFilterHost.disconnectLocked(); 606 mInputFilterHost = null; 607 try { 608 oldFilter.uninstall(); 609 } catch (RemoteException re) { 610 /* ignore */ 611 } 612 } 613 614 if (filter != null) { 615 mInputFilter = filter; 616 mInputFilterHost = new InputFilterHost(); 617 try { 618 filter.install(mInputFilterHost); 619 } catch (RemoteException re) { 620 /* ignore */ 621 } 622 } 623 624 nativeSetInputFilterEnabled(mPtr, filter != null); 625 } 626 } 627 628 @Override // Binder call injectInputEvent(InputEvent event, int mode)629 public boolean injectInputEvent(InputEvent event, int mode) { 630 return injectInputEventInternal(event, mode); 631 } 632 injectInputEventInternal(InputEvent event, int mode)633 private boolean injectInputEventInternal(InputEvent event, int mode) { 634 if (event == null) { 635 throw new IllegalArgumentException("event must not be null"); 636 } 637 if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC 638 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH 639 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { 640 throw new IllegalArgumentException("mode is invalid"); 641 } 642 643 final int pid = Binder.getCallingPid(); 644 final int uid = Binder.getCallingUid(); 645 final long ident = Binder.clearCallingIdentity(); 646 final int result; 647 try { 648 result = nativeInjectInputEvent(mPtr, event, pid, uid, mode, 649 INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); 650 } finally { 651 Binder.restoreCallingIdentity(ident); 652 } 653 switch (result) { 654 case INPUT_EVENT_INJECTION_PERMISSION_DENIED: 655 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); 656 throw new SecurityException( 657 "Injecting to another application requires INJECT_EVENTS permission"); 658 case INPUT_EVENT_INJECTION_SUCCEEDED: 659 return true; 660 case INPUT_EVENT_INJECTION_TIMED_OUT: 661 Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); 662 return false; 663 case INPUT_EVENT_INJECTION_FAILED: 664 default: 665 Slog.w(TAG, "Input event injection from pid " + pid + " failed."); 666 return false; 667 } 668 } 669 670 /** 671 * Gets information about the input device with the specified id. 672 * @param deviceId The device id. 673 * @return The input device or null if not found. 674 */ 675 @Override // Binder call getInputDevice(int deviceId)676 public InputDevice getInputDevice(int deviceId) { 677 synchronized (mInputDevicesLock) { 678 final int count = mInputDevices.length; 679 for (int i = 0; i < count; i++) { 680 final InputDevice inputDevice = mInputDevices[i]; 681 if (inputDevice.getId() == deviceId) { 682 return inputDevice; 683 } 684 } 685 } 686 return null; 687 } 688 689 // Binder call 690 @Override isInputDeviceEnabled(int deviceId)691 public boolean isInputDeviceEnabled(int deviceId) { 692 return nativeIsInputDeviceEnabled(mPtr, deviceId); 693 } 694 695 // Binder call 696 @Override enableInputDevice(int deviceId)697 public void enableInputDevice(int deviceId) { 698 if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE, 699 "enableInputDevice()")) { 700 throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission"); 701 } 702 nativeEnableInputDevice(mPtr, deviceId); 703 } 704 705 // Binder call 706 @Override disableInputDevice(int deviceId)707 public void disableInputDevice(int deviceId) { 708 if (!checkCallingPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE, 709 "disableInputDevice()")) { 710 throw new SecurityException("Requires DISABLE_INPUT_DEVICE permission"); 711 } 712 nativeDisableInputDevice(mPtr, deviceId); 713 } 714 715 /** 716 * Gets the ids of all input devices in the system. 717 * @return The input device ids. 718 */ 719 @Override // Binder call getInputDeviceIds()720 public int[] getInputDeviceIds() { 721 synchronized (mInputDevicesLock) { 722 final int count = mInputDevices.length; 723 int[] ids = new int[count]; 724 for (int i = 0; i < count; i++) { 725 ids[i] = mInputDevices[i].getId(); 726 } 727 return ids; 728 } 729 } 730 731 /** 732 * Gets all input devices in the system. 733 * @return The array of input devices. 734 */ getInputDevices()735 public InputDevice[] getInputDevices() { 736 synchronized (mInputDevicesLock) { 737 return mInputDevices; 738 } 739 } 740 741 @Override // Binder call registerInputDevicesChangedListener(IInputDevicesChangedListener listener)742 public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) { 743 if (listener == null) { 744 throw new IllegalArgumentException("listener must not be null"); 745 } 746 747 synchronized (mInputDevicesLock) { 748 int callingPid = Binder.getCallingPid(); 749 if (mInputDevicesChangedListeners.get(callingPid) != null) { 750 throw new SecurityException("The calling process has already " 751 + "registered an InputDevicesChangedListener."); 752 } 753 754 InputDevicesChangedListenerRecord record = 755 new InputDevicesChangedListenerRecord(callingPid, listener); 756 try { 757 IBinder binder = listener.asBinder(); 758 binder.linkToDeath(record, 0); 759 } catch (RemoteException ex) { 760 // give up 761 throw new RuntimeException(ex); 762 } 763 764 mInputDevicesChangedListeners.put(callingPid, record); 765 } 766 } 767 onInputDevicesChangedListenerDied(int pid)768 private void onInputDevicesChangedListenerDied(int pid) { 769 synchronized (mInputDevicesLock) { 770 mInputDevicesChangedListeners.remove(pid); 771 } 772 } 773 774 // Must be called on handler. deliverInputDevicesChanged(InputDevice[] oldInputDevices)775 private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) { 776 // Scan for changes. 777 int numFullKeyboardsAdded = 0; 778 mTempInputDevicesChangedListenersToNotify.clear(); 779 mTempFullKeyboards.clear(); 780 final int numListeners; 781 final int[] deviceIdAndGeneration; 782 synchronized (mInputDevicesLock) { 783 if (!mInputDevicesChangedPending) { 784 return; 785 } 786 mInputDevicesChangedPending = false; 787 788 numListeners = mInputDevicesChangedListeners.size(); 789 for (int i = 0; i < numListeners; i++) { 790 mTempInputDevicesChangedListenersToNotify.add( 791 mInputDevicesChangedListeners.valueAt(i)); 792 } 793 794 final int numDevices = mInputDevices.length; 795 deviceIdAndGeneration = new int[numDevices * 2]; 796 for (int i = 0; i < numDevices; i++) { 797 final InputDevice inputDevice = mInputDevices[i]; 798 deviceIdAndGeneration[i * 2] = inputDevice.getId(); 799 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration(); 800 801 if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) { 802 if (!containsInputDeviceWithDescriptor(oldInputDevices, 803 inputDevice.getDescriptor())) { 804 mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice); 805 } else { 806 mTempFullKeyboards.add(inputDevice); 807 } 808 } 809 } 810 } 811 812 // Notify listeners. 813 for (int i = 0; i < numListeners; i++) { 814 mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged( 815 deviceIdAndGeneration); 816 } 817 mTempInputDevicesChangedListenersToNotify.clear(); 818 819 // Check for missing keyboard layouts. 820 List<InputDevice> keyboardsMissingLayout = new ArrayList<>(); 821 final int numFullKeyboards = mTempFullKeyboards.size(); 822 synchronized (mDataStore) { 823 for (int i = 0; i < numFullKeyboards; i++) { 824 final InputDevice inputDevice = mTempFullKeyboards.get(i); 825 String layout = 826 getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier()); 827 if (layout == null) { 828 layout = getDefaultKeyboardLayout(inputDevice); 829 if (layout != null) { 830 setCurrentKeyboardLayoutForInputDevice( 831 inputDevice.getIdentifier(), layout); 832 } 833 } 834 if (layout == null) { 835 keyboardsMissingLayout.add(inputDevice); 836 } 837 } 838 } 839 840 if (mNotificationManager != null) { 841 if (!keyboardsMissingLayout.isEmpty()) { 842 if (keyboardsMissingLayout.size() > 1) { 843 // We have more than one keyboard missing a layout, so drop the 844 // user at the generic input methods page so they can pick which 845 // one to set. 846 showMissingKeyboardLayoutNotification(null); 847 } else { 848 showMissingKeyboardLayoutNotification(keyboardsMissingLayout.get(0)); 849 } 850 } else if (mKeyboardLayoutNotificationShown) { 851 hideMissingKeyboardLayoutNotification(); 852 } 853 } 854 mTempFullKeyboards.clear(); 855 } 856 getDefaultKeyboardLayout(final InputDevice d)857 private String getDefaultKeyboardLayout(final InputDevice d) { 858 final Locale systemLocale = mContext.getResources().getConfiguration().locale; 859 // If our locale doesn't have a language for some reason, then we don't really have a 860 // reasonable default. 861 if (TextUtils.isEmpty(systemLocale.getLanguage())) { 862 return null; 863 } 864 final List<KeyboardLayout> layouts = new ArrayList<>(); 865 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() { 866 @Override 867 public void visitKeyboardLayout(Resources resources, 868 int keyboardLayoutResId, KeyboardLayout layout) { 869 // Only select a default when we know the layout is appropriate. For now, this 870 // means its a custom layout for a specific keyboard. 871 if (layout.getVendorId() != d.getVendorId() 872 || layout.getProductId() != d.getProductId()) { 873 return; 874 } 875 final LocaleList locales = layout.getLocales(); 876 final int numLocales = locales.size(); 877 for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) { 878 if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) { 879 layouts.add(layout); 880 break; 881 } 882 } 883 } 884 }); 885 886 if (layouts.isEmpty()) { 887 return null; 888 } 889 890 // First sort so that ones with higher priority are listed at the top 891 Collections.sort(layouts); 892 // Next we want to try to find an exact match of language, country and variant. 893 final int N = layouts.size(); 894 for (int i = 0; i < N; i++) { 895 KeyboardLayout layout = layouts.get(i); 896 final LocaleList locales = layout.getLocales(); 897 final int numLocales = locales.size(); 898 for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) { 899 final Locale locale = locales.get(localeIndex); 900 if (locale.getCountry().equals(systemLocale.getCountry()) 901 && locale.getVariant().equals(systemLocale.getVariant())) { 902 return layout.getDescriptor(); 903 } 904 } 905 } 906 // Then try an exact match of language and country 907 for (int i = 0; i < N; i++) { 908 KeyboardLayout layout = layouts.get(i); 909 final LocaleList locales = layout.getLocales(); 910 final int numLocales = locales.size(); 911 for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) { 912 final Locale locale = locales.get(localeIndex); 913 if (locale.getCountry().equals(systemLocale.getCountry())) { 914 return layout.getDescriptor(); 915 } 916 } 917 } 918 919 // Give up and just use the highest priority layout with matching language 920 return layouts.get(0).getDescriptor(); 921 } 922 isCompatibleLocale(Locale systemLocale, Locale keyboardLocale)923 private static boolean isCompatibleLocale(Locale systemLocale, Locale keyboardLocale) { 924 // Different languages are never compatible 925 if (!systemLocale.getLanguage().equals(keyboardLocale.getLanguage())) { 926 return false; 927 } 928 // If both the system and the keyboard layout have a country specifier, they must be equal. 929 if (!TextUtils.isEmpty(systemLocale.getCountry()) 930 && !TextUtils.isEmpty(keyboardLocale.getCountry()) 931 && !systemLocale.getCountry().equals(keyboardLocale.getCountry())) { 932 return false; 933 } 934 return true; 935 } 936 937 @Override // Binder call & native callback getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation)938 public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, 939 int surfaceRotation) { 940 if (inputDeviceDescriptor == null) { 941 throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); 942 } 943 944 synchronized (mDataStore) { 945 return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation); 946 } 947 } 948 949 @Override // Binder call setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation, TouchCalibration calibration)950 public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation, 951 TouchCalibration calibration) { 952 if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION, 953 "setTouchCalibrationForInputDevice()")) { 954 throw new SecurityException("Requires SET_INPUT_CALIBRATION permission"); 955 } 956 if (inputDeviceDescriptor == null) { 957 throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); 958 } 959 if (calibration == null) { 960 throw new IllegalArgumentException("calibration must not be null"); 961 } 962 if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) { 963 throw new IllegalArgumentException("surfaceRotation value out of bounds"); 964 } 965 966 synchronized (mDataStore) { 967 try { 968 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation, 969 calibration)) { 970 nativeReloadCalibration(mPtr); 971 } 972 } finally { 973 mDataStore.saveIfNeeded(); 974 } 975 } 976 } 977 978 @Override // Binder call isInTabletMode()979 public int isInTabletMode() { 980 if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, 981 "isInTabletMode()")) { 982 throw new SecurityException("Requires TABLET_MODE permission"); 983 } 984 return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_TABLET_MODE); 985 } 986 987 @Override // Binder call isMicMuted()988 public int isMicMuted() { 989 return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MUTE_DEVICE); 990 } 991 992 @Override // Binder call registerTabletModeChangedListener(ITabletModeChangedListener listener)993 public void registerTabletModeChangedListener(ITabletModeChangedListener listener) { 994 if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, 995 "registerTabletModeChangedListener()")) { 996 throw new SecurityException("Requires TABLET_MODE_LISTENER permission"); 997 } 998 if (listener == null) { 999 throw new IllegalArgumentException("listener must not be null"); 1000 } 1001 1002 synchronized (mTabletModeLock) { 1003 final int callingPid = Binder.getCallingPid(); 1004 if (mTabletModeChangedListeners.get(callingPid) != null) { 1005 throw new IllegalStateException("The calling process has already registered " 1006 + "a TabletModeChangedListener."); 1007 } 1008 TabletModeChangedListenerRecord record = 1009 new TabletModeChangedListenerRecord(callingPid, listener); 1010 try { 1011 IBinder binder = listener.asBinder(); 1012 binder.linkToDeath(record, 0); 1013 } catch (RemoteException ex) { 1014 throw new RuntimeException(ex); 1015 } 1016 mTabletModeChangedListeners.put(callingPid, record); 1017 } 1018 } 1019 onTabletModeChangedListenerDied(int pid)1020 private void onTabletModeChangedListenerDied(int pid) { 1021 synchronized (mTabletModeLock) { 1022 mTabletModeChangedListeners.remove(pid); 1023 } 1024 } 1025 1026 // Must be called on handler deliverTabletModeChanged(long whenNanos, boolean inTabletMode)1027 private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) { 1028 mTempTabletModeChangedListenersToNotify.clear(); 1029 final int numListeners; 1030 synchronized (mTabletModeLock) { 1031 numListeners = mTabletModeChangedListeners.size(); 1032 for (int i = 0; i < numListeners; i++) { 1033 mTempTabletModeChangedListenersToNotify.add( 1034 mTabletModeChangedListeners.valueAt(i)); 1035 } 1036 } 1037 for (int i = 0; i < numListeners; i++) { 1038 mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged( 1039 whenNanos, inTabletMode); 1040 } 1041 } 1042 1043 // Must be called on handler. showMissingKeyboardLayoutNotification(InputDevice device)1044 private void showMissingKeyboardLayoutNotification(InputDevice device) { 1045 if (!mKeyboardLayoutNotificationShown) { 1046 final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS); 1047 if (device != null) { 1048 intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier()); 1049 } 1050 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1051 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 1052 | Intent.FLAG_ACTIVITY_CLEAR_TOP); 1053 final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0, 1054 intent, 0, null, UserHandle.CURRENT); 1055 1056 Resources r = mContext.getResources(); 1057 Notification notification = 1058 new Notification.Builder(mContext, SystemNotificationChannels.PHYSICAL_KEYBOARD) 1059 .setContentTitle(r.getString( 1060 R.string.select_keyboard_layout_notification_title)) 1061 .setContentText(r.getString( 1062 R.string.select_keyboard_layout_notification_message)) 1063 .setContentIntent(keyboardLayoutIntent) 1064 .setSmallIcon(R.drawable.ic_settings_language) 1065 .setColor(mContext.getColor( 1066 com.android.internal.R.color.system_notification_accent_color)) 1067 .build(); 1068 mNotificationManager.notifyAsUser(null, 1069 SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT, 1070 notification, UserHandle.ALL); 1071 mKeyboardLayoutNotificationShown = true; 1072 } 1073 } 1074 1075 // Must be called on handler. hideMissingKeyboardLayoutNotification()1076 private void hideMissingKeyboardLayoutNotification() { 1077 if (mKeyboardLayoutNotificationShown) { 1078 mKeyboardLayoutNotificationShown = false; 1079 mNotificationManager.cancelAsUser(null, 1080 SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT, 1081 UserHandle.ALL); 1082 } 1083 } 1084 1085 // Must be called on handler. updateKeyboardLayouts()1086 private void updateKeyboardLayouts() { 1087 // Scan all input devices state for keyboard layouts that have been uninstalled. 1088 final HashSet<String> availableKeyboardLayouts = new HashSet<String>(); 1089 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() { 1090 @Override 1091 public void visitKeyboardLayout(Resources resources, 1092 int keyboardLayoutResId, KeyboardLayout layout) { 1093 availableKeyboardLayouts.add(layout.getDescriptor()); 1094 } 1095 }); 1096 synchronized (mDataStore) { 1097 try { 1098 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts); 1099 } finally { 1100 mDataStore.saveIfNeeded(); 1101 } 1102 } 1103 1104 // Reload keyboard layouts. 1105 reloadKeyboardLayouts(); 1106 } 1107 containsInputDeviceWithDescriptor(InputDevice[] inputDevices, String descriptor)1108 private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices, 1109 String descriptor) { 1110 final int numDevices = inputDevices.length; 1111 for (int i = 0; i < numDevices; i++) { 1112 final InputDevice inputDevice = inputDevices[i]; 1113 if (inputDevice.getDescriptor().equals(descriptor)) { 1114 return true; 1115 } 1116 } 1117 return false; 1118 } 1119 1120 @Override // Binder call getKeyboardLayouts()1121 public KeyboardLayout[] getKeyboardLayouts() { 1122 final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>(); 1123 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() { 1124 @Override 1125 public void visitKeyboardLayout(Resources resources, 1126 int keyboardLayoutResId, KeyboardLayout layout) { 1127 list.add(layout); 1128 } 1129 }); 1130 return list.toArray(new KeyboardLayout[list.size()]); 1131 } 1132 1133 @Override // Binder call getKeyboardLayoutsForInputDevice( final InputDeviceIdentifier identifier)1134 public KeyboardLayout[] getKeyboardLayoutsForInputDevice( 1135 final InputDeviceIdentifier identifier) { 1136 final String[] enabledLayoutDescriptors = 1137 getEnabledKeyboardLayoutsForInputDevice(identifier); 1138 final ArrayList<KeyboardLayout> enabledLayouts = 1139 new ArrayList<KeyboardLayout>(enabledLayoutDescriptors.length); 1140 final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<KeyboardLayout>(); 1141 visitAllKeyboardLayouts(new KeyboardLayoutVisitor() { 1142 boolean mHasSeenDeviceSpecificLayout; 1143 1144 @Override 1145 public void visitKeyboardLayout(Resources resources, 1146 int keyboardLayoutResId, KeyboardLayout layout) { 1147 // First check if it's enabled. If the keyboard layout is enabled then we always 1148 // want to return it as a possible layout for the device. 1149 for (String s : enabledLayoutDescriptors) { 1150 if (s != null && s.equals(layout.getDescriptor())) { 1151 enabledLayouts.add(layout); 1152 return; 1153 } 1154 } 1155 // Next find any potential layouts that aren't yet enabled for the device. For 1156 // devices that have special layouts we assume there's a reason that the generic 1157 // layouts don't work for them so we don't want to return them since it's likely 1158 // to result in a poor user experience. 1159 if (layout.getVendorId() == identifier.getVendorId() 1160 && layout.getProductId() == identifier.getProductId()) { 1161 if (!mHasSeenDeviceSpecificLayout) { 1162 mHasSeenDeviceSpecificLayout = true; 1163 potentialLayouts.clear(); 1164 } 1165 potentialLayouts.add(layout); 1166 } else if (layout.getVendorId() == -1 && layout.getProductId() == -1 1167 && !mHasSeenDeviceSpecificLayout) { 1168 potentialLayouts.add(layout); 1169 } 1170 } 1171 }); 1172 final int enabledLayoutSize = enabledLayouts.size(); 1173 final int potentialLayoutSize = potentialLayouts.size(); 1174 KeyboardLayout[] layouts = new KeyboardLayout[enabledLayoutSize + potentialLayoutSize]; 1175 enabledLayouts.toArray(layouts); 1176 for (int i = 0; i < potentialLayoutSize; i++) { 1177 layouts[enabledLayoutSize + i] = potentialLayouts.get(i); 1178 } 1179 return layouts; 1180 } 1181 1182 @Override // Binder call getKeyboardLayout(String keyboardLayoutDescriptor)1183 public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { 1184 if (keyboardLayoutDescriptor == null) { 1185 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); 1186 } 1187 1188 final KeyboardLayout[] result = new KeyboardLayout[1]; 1189 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() { 1190 @Override 1191 public void visitKeyboardLayout(Resources resources, 1192 int keyboardLayoutResId, KeyboardLayout layout) { 1193 result[0] = layout; 1194 } 1195 }); 1196 if (result[0] == null) { 1197 Slog.w(TAG, "Could not get keyboard layout with descriptor '" 1198 + keyboardLayoutDescriptor + "'."); 1199 } 1200 return result[0]; 1201 } 1202 visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor)1203 private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) { 1204 final PackageManager pm = mContext.getPackageManager(); 1205 Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS); 1206 for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent, 1207 PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE 1208 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE)) { 1209 final ActivityInfo activityInfo = resolveInfo.activityInfo; 1210 final int priority = resolveInfo.priority; 1211 visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor); 1212 } 1213 } 1214 visitKeyboardLayout(String keyboardLayoutDescriptor, KeyboardLayoutVisitor visitor)1215 private void visitKeyboardLayout(String keyboardLayoutDescriptor, 1216 KeyboardLayoutVisitor visitor) { 1217 KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor); 1218 if (d != null) { 1219 final PackageManager pm = mContext.getPackageManager(); 1220 try { 1221 ActivityInfo receiver = pm.getReceiverInfo( 1222 new ComponentName(d.packageName, d.receiverName), 1223 PackageManager.GET_META_DATA 1224 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1225 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 1226 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor); 1227 } catch (NameNotFoundException ex) { 1228 } 1229 } 1230 } 1231 visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver, String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor)1232 private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver, 1233 String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor) { 1234 Bundle metaData = receiver.metaData; 1235 if (metaData == null) { 1236 return; 1237 } 1238 1239 int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS); 1240 if (configResId == 0) { 1241 Slog.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS 1242 + "' on receiver " + receiver.packageName + "/" + receiver.name); 1243 return; 1244 } 1245 1246 CharSequence receiverLabel = receiver.loadLabel(pm); 1247 String collection = receiverLabel != null ? receiverLabel.toString() : ""; 1248 int priority; 1249 if ((receiver.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 1250 priority = requestedPriority; 1251 } else { 1252 priority = 0; 1253 } 1254 1255 try { 1256 Resources resources = pm.getResourcesForApplication(receiver.applicationInfo); 1257 XmlResourceParser parser = resources.getXml(configResId); 1258 try { 1259 XmlUtils.beginDocument(parser, "keyboard-layouts"); 1260 1261 for (;;) { 1262 XmlUtils.nextElement(parser); 1263 String element = parser.getName(); 1264 if (element == null) { 1265 break; 1266 } 1267 if (element.equals("keyboard-layout")) { 1268 TypedArray a = resources.obtainAttributes( 1269 parser, com.android.internal.R.styleable.KeyboardLayout); 1270 try { 1271 String name = a.getString( 1272 com.android.internal.R.styleable.KeyboardLayout_name); 1273 String label = a.getString( 1274 com.android.internal.R.styleable.KeyboardLayout_label); 1275 int keyboardLayoutResId = a.getResourceId( 1276 com.android.internal.R.styleable.KeyboardLayout_keyboardLayout, 1277 0); 1278 String languageTags = a.getString( 1279 com.android.internal.R.styleable.KeyboardLayout_locale); 1280 LocaleList locales = getLocalesFromLanguageTags(languageTags); 1281 int vid = a.getInt( 1282 com.android.internal.R.styleable.KeyboardLayout_vendorId, -1); 1283 int pid = a.getInt( 1284 com.android.internal.R.styleable.KeyboardLayout_productId, -1); 1285 1286 if (name == null || label == null || keyboardLayoutResId == 0) { 1287 Slog.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' " 1288 + "attributes in keyboard layout " 1289 + "resource from receiver " 1290 + receiver.packageName + "/" + receiver.name); 1291 } else { 1292 String descriptor = KeyboardLayoutDescriptor.format( 1293 receiver.packageName, receiver.name, name); 1294 if (keyboardName == null || name.equals(keyboardName)) { 1295 KeyboardLayout layout = new KeyboardLayout( 1296 descriptor, label, collection, priority, 1297 locales, vid, pid); 1298 visitor.visitKeyboardLayout( 1299 resources, keyboardLayoutResId, layout); 1300 } 1301 } 1302 } finally { 1303 a.recycle(); 1304 } 1305 } else { 1306 Slog.w(TAG, "Skipping unrecognized element '" + element 1307 + "' in keyboard layout resource from receiver " 1308 + receiver.packageName + "/" + receiver.name); 1309 } 1310 } 1311 } finally { 1312 parser.close(); 1313 } 1314 } catch (Exception ex) { 1315 Slog.w(TAG, "Could not parse keyboard layout resource from receiver " 1316 + receiver.packageName + "/" + receiver.name, ex); 1317 } 1318 } 1319 1320 @NonNull getLocalesFromLanguageTags(String languageTags)1321 private static LocaleList getLocalesFromLanguageTags(String languageTags) { 1322 if (TextUtils.isEmpty(languageTags)) { 1323 return LocaleList.getEmptyLocaleList(); 1324 } 1325 return LocaleList.forLanguageTags(languageTags.replace('|', ',')); 1326 } 1327 1328 /** 1329 * Builds a layout descriptor for the vendor/product. This returns the 1330 * descriptor for ids that aren't useful (such as the default 0, 0). 1331 */ getLayoutDescriptor(InputDeviceIdentifier identifier)1332 private String getLayoutDescriptor(InputDeviceIdentifier identifier) { 1333 if (identifier == null || identifier.getDescriptor() == null) { 1334 throw new IllegalArgumentException("identifier and descriptor must not be null"); 1335 } 1336 1337 if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) { 1338 return identifier.getDescriptor(); 1339 } 1340 StringBuilder bob = new StringBuilder(); 1341 bob.append("vendor:").append(identifier.getVendorId()); 1342 bob.append(",product:").append(identifier.getProductId()); 1343 return bob.toString(); 1344 } 1345 1346 @Override // Binder call getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier)1347 public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) { 1348 1349 String key = getLayoutDescriptor(identifier); 1350 synchronized (mDataStore) { 1351 String layout = null; 1352 // try loading it using the layout descriptor if we have it 1353 layout = mDataStore.getCurrentKeyboardLayout(key); 1354 if (layout == null && !key.equals(identifier.getDescriptor())) { 1355 // if it doesn't exist fall back to the device descriptor 1356 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor()); 1357 } 1358 if (DEBUG) { 1359 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got " 1360 + layout); 1361 } 1362 return layout; 1363 } 1364 } 1365 1366 @Override // Binder call setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1367 public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, 1368 String keyboardLayoutDescriptor) { 1369 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT, 1370 "setCurrentKeyboardLayoutForInputDevice()")) { 1371 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission"); 1372 } 1373 if (keyboardLayoutDescriptor == null) { 1374 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); 1375 } 1376 1377 String key = getLayoutDescriptor(identifier); 1378 synchronized (mDataStore) { 1379 try { 1380 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) { 1381 if (DEBUG) { 1382 Slog.d(TAG, "Saved keyboard layout using " + key); 1383 } 1384 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS); 1385 } 1386 } finally { 1387 mDataStore.saveIfNeeded(); 1388 } 1389 } 1390 } 1391 1392 @Override // Binder call getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier)1393 public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) { 1394 String key = getLayoutDescriptor(identifier); 1395 synchronized (mDataStore) { 1396 String[] layouts = mDataStore.getKeyboardLayouts(key); 1397 if ((layouts == null || layouts.length == 0) 1398 && !key.equals(identifier.getDescriptor())) { 1399 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor()); 1400 } 1401 return layouts; 1402 } 1403 } 1404 1405 @Override // Binder call addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1406 public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, 1407 String keyboardLayoutDescriptor) { 1408 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT, 1409 "addKeyboardLayoutForInputDevice()")) { 1410 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission"); 1411 } 1412 if (keyboardLayoutDescriptor == null) { 1413 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); 1414 } 1415 1416 String key = getLayoutDescriptor(identifier); 1417 synchronized (mDataStore) { 1418 try { 1419 String oldLayout = mDataStore.getCurrentKeyboardLayout(key); 1420 if (oldLayout == null && !key.equals(identifier.getDescriptor())) { 1421 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor()); 1422 } 1423 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor) 1424 && !Objects.equals(oldLayout, 1425 mDataStore.getCurrentKeyboardLayout(key))) { 1426 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS); 1427 } 1428 } finally { 1429 mDataStore.saveIfNeeded(); 1430 } 1431 } 1432 } 1433 1434 @Override // Binder call removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1435 public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, 1436 String keyboardLayoutDescriptor) { 1437 if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT, 1438 "removeKeyboardLayoutForInputDevice()")) { 1439 throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission"); 1440 } 1441 if (keyboardLayoutDescriptor == null) { 1442 throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); 1443 } 1444 1445 String key = getLayoutDescriptor(identifier); 1446 synchronized (mDataStore) { 1447 try { 1448 String oldLayout = mDataStore.getCurrentKeyboardLayout(key); 1449 if (oldLayout == null && !key.equals(identifier.getDescriptor())) { 1450 oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor()); 1451 } 1452 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor); 1453 if (!key.equals(identifier.getDescriptor())) { 1454 // We need to remove from both places to ensure it is gone 1455 removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(), 1456 keyboardLayoutDescriptor); 1457 } 1458 if (removed && !Objects.equals(oldLayout, 1459 mDataStore.getCurrentKeyboardLayout(key))) { 1460 mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS); 1461 } 1462 } finally { 1463 mDataStore.saveIfNeeded(); 1464 } 1465 } 1466 } 1467 switchKeyboardLayout(int deviceId, int direction)1468 public void switchKeyboardLayout(int deviceId, int direction) { 1469 mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget(); 1470 } 1471 1472 // Must be called on handler. handleSwitchKeyboardLayout(int deviceId, int direction)1473 private void handleSwitchKeyboardLayout(int deviceId, int direction) { 1474 final InputDevice device = getInputDevice(deviceId); 1475 if (device != null) { 1476 final boolean changed; 1477 final String keyboardLayoutDescriptor; 1478 1479 String key = getLayoutDescriptor(device.getIdentifier()); 1480 synchronized (mDataStore) { 1481 try { 1482 changed = mDataStore.switchKeyboardLayout(key, direction); 1483 keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout( 1484 key); 1485 } finally { 1486 mDataStore.saveIfNeeded(); 1487 } 1488 } 1489 1490 if (changed) { 1491 if (mSwitchedKeyboardLayoutToast != null) { 1492 mSwitchedKeyboardLayoutToast.cancel(); 1493 mSwitchedKeyboardLayoutToast = null; 1494 } 1495 if (keyboardLayoutDescriptor != null) { 1496 KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor); 1497 if (keyboardLayout != null) { 1498 mSwitchedKeyboardLayoutToast = Toast.makeText( 1499 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT); 1500 mSwitchedKeyboardLayoutToast.show(); 1501 } 1502 } 1503 1504 reloadKeyboardLayouts(); 1505 } 1506 } 1507 } 1508 setFocusedApplication(int displayId, InputApplicationHandle application)1509 public void setFocusedApplication(int displayId, InputApplicationHandle application) { 1510 nativeSetFocusedApplication(mPtr, displayId, application); 1511 } 1512 setFocusedDisplay(int displayId)1513 public void setFocusedDisplay(int displayId) { 1514 nativeSetFocusedDisplay(mPtr, displayId); 1515 } 1516 1517 /** Clean up input window handles of the given display. */ onDisplayRemoved(int displayId)1518 public void onDisplayRemoved(int displayId) { 1519 nativeSetInputWindows(mPtr, null /* windowHandles */, displayId); 1520 } 1521 1522 @Override requestPointerCapture(IBinder windowToken, boolean enabled)1523 public void requestPointerCapture(IBinder windowToken, boolean enabled) { 1524 if (mFocusedWindow == null || mFocusedWindow.asBinder() != windowToken) { 1525 Slog.e(TAG, "requestPointerCapture called for a window that has no focus: " 1526 + windowToken); 1527 return; 1528 } 1529 if (mFocusedWindowHasCapture == enabled) { 1530 Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled")); 1531 return; 1532 } 1533 setPointerCapture(enabled); 1534 } 1535 setPointerCapture(boolean enabled)1536 private void setPointerCapture(boolean enabled) { 1537 if (mFocusedWindowHasCapture != enabled) { 1538 mFocusedWindowHasCapture = enabled; 1539 try { 1540 mFocusedWindow.dispatchPointerCaptureChanged(enabled); 1541 } catch (RemoteException ex) { 1542 /* ignore */ 1543 } 1544 nativeSetPointerCapture(mPtr, enabled); 1545 } 1546 } 1547 setInputDispatchMode(boolean enabled, boolean frozen)1548 public void setInputDispatchMode(boolean enabled, boolean frozen) { 1549 nativeSetInputDispatchMode(mPtr, enabled, frozen); 1550 } 1551 setSystemUiVisibility(int visibility)1552 public void setSystemUiVisibility(int visibility) { 1553 nativeSetSystemUiVisibility(mPtr, visibility); 1554 } 1555 1556 /** 1557 * Atomically transfers touch focus from one window to another as identified by 1558 * their input channels. It is possible for multiple windows to have 1559 * touch focus if they support split touch dispatch 1560 * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this 1561 * method only transfers touch focus of the specified window without affecting 1562 * other windows that may also have touch focus at the same time. 1563 * @param fromChannel The channel of a window that currently has touch focus. 1564 * @param toChannel The channel of the window that should receive touch focus in 1565 * place of the first. 1566 * @return True if the transfer was successful. False if the window with the 1567 * specified channel did not actually have touch focus at the time of the request. 1568 */ transferTouchFocus(InputChannel fromChannel, InputChannel toChannel)1569 public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) { 1570 if (fromChannel == null) { 1571 throw new IllegalArgumentException("fromChannel must not be null."); 1572 } 1573 if (toChannel == null) { 1574 throw new IllegalArgumentException("toChannel must not be null."); 1575 } 1576 return nativeTransferTouchFocus(mPtr, fromChannel, toChannel); 1577 } 1578 1579 @Override // Binder call tryPointerSpeed(int speed)1580 public void tryPointerSpeed(int speed) { 1581 if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED, 1582 "tryPointerSpeed()")) { 1583 throw new SecurityException("Requires SET_POINTER_SPEED permission"); 1584 } 1585 1586 if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) { 1587 throw new IllegalArgumentException("speed out of range"); 1588 } 1589 1590 setPointerSpeedUnchecked(speed); 1591 } 1592 updatePointerSpeedFromSettings()1593 private void updatePointerSpeedFromSettings() { 1594 int speed = getPointerSpeedSetting(); 1595 setPointerSpeedUnchecked(speed); 1596 } 1597 setPointerSpeedUnchecked(int speed)1598 private void setPointerSpeedUnchecked(int speed) { 1599 speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED), 1600 InputManager.MAX_POINTER_SPEED); 1601 nativeSetPointerSpeed(mPtr, speed); 1602 } 1603 registerPointerSpeedSettingObserver()1604 private void registerPointerSpeedSettingObserver() { 1605 mContext.getContentResolver().registerContentObserver( 1606 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true, 1607 new ContentObserver(mHandler) { 1608 @Override 1609 public void onChange(boolean selfChange) { 1610 updatePointerSpeedFromSettings(); 1611 } 1612 }, UserHandle.USER_ALL); 1613 } 1614 getPointerSpeedSetting()1615 private int getPointerSpeedSetting() { 1616 int speed = InputManager.DEFAULT_POINTER_SPEED; 1617 try { 1618 speed = Settings.System.getIntForUser(mContext.getContentResolver(), 1619 Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT); 1620 } catch (SettingNotFoundException snfe) { 1621 } 1622 return speed; 1623 } 1624 updateShowTouchesFromSettings()1625 private void updateShowTouchesFromSettings() { 1626 int setting = getShowTouchesSetting(0); 1627 nativeSetShowTouches(mPtr, setting != 0); 1628 } 1629 registerShowTouchesSettingObserver()1630 private void registerShowTouchesSettingObserver() { 1631 mContext.getContentResolver().registerContentObserver( 1632 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true, 1633 new ContentObserver(mHandler) { 1634 @Override 1635 public void onChange(boolean selfChange) { 1636 updateShowTouchesFromSettings(); 1637 } 1638 }, UserHandle.USER_ALL); 1639 } 1640 updateAccessibilityLargePointerFromSettings()1641 private void updateAccessibilityLargePointerFromSettings() { 1642 final int accessibilityConfig = Settings.Secure.getIntForUser( 1643 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 1644 0, UserHandle.USER_CURRENT); 1645 PointerIcon.setUseLargeIcons(accessibilityConfig == 1); 1646 nativeReloadPointerIcons(mPtr); 1647 } 1648 registerAccessibilityLargePointerSettingObserver()1649 private void registerAccessibilityLargePointerSettingObserver() { 1650 mContext.getContentResolver().registerContentObserver( 1651 Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON), true, 1652 new ContentObserver(mHandler) { 1653 @Override 1654 public void onChange(boolean selfChange) { 1655 updateAccessibilityLargePointerFromSettings(); 1656 } 1657 }, UserHandle.USER_ALL); 1658 } 1659 updateDeepPressStatusFromSettings(String reason)1660 private void updateDeepPressStatusFromSettings(String reason) { 1661 // Not using ViewConfiguration.getLongPressTimeout here because it may return a stale value 1662 final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(), 1663 Settings.Secure.LONG_PRESS_TIMEOUT, ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT, 1664 UserHandle.USER_CURRENT); 1665 final boolean featureEnabledFlag = 1666 DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT, 1667 DEEP_PRESS_ENABLED, true /* default */); 1668 final boolean enabled = 1669 featureEnabledFlag && timeout <= ViewConfiguration.DEFAULT_LONG_PRESS_TIMEOUT; 1670 Log.i(TAG, 1671 (enabled ? "Enabling" : "Disabling") + " motion classifier because " + reason 1672 + ": feature " + (featureEnabledFlag ? "enabled" : "disabled") 1673 + ", long press timeout = " + timeout); 1674 nativeSetMotionClassifierEnabled(mPtr, enabled); 1675 } 1676 registerLongPressTimeoutObserver()1677 private void registerLongPressTimeoutObserver() { 1678 mContext.getContentResolver().registerContentObserver( 1679 Settings.Secure.getUriFor(Settings.Secure.LONG_PRESS_TIMEOUT), true, 1680 new ContentObserver(mHandler) { 1681 @Override 1682 public void onChange(boolean selfChange) { 1683 updateDeepPressStatusFromSettings("timeout changed"); 1684 } 1685 }, UserHandle.USER_ALL); 1686 } 1687 getShowTouchesSetting(int defaultValue)1688 private int getShowTouchesSetting(int defaultValue) { 1689 int result = defaultValue; 1690 try { 1691 result = Settings.System.getIntForUser(mContext.getContentResolver(), 1692 Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT); 1693 } catch (SettingNotFoundException snfe) { 1694 } 1695 return result; 1696 } 1697 1698 // Binder call 1699 @Override vibrate(int deviceId, long[] pattern, int repeat, IBinder token)1700 public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) { 1701 if (repeat >= pattern.length) { 1702 throw new ArrayIndexOutOfBoundsException(); 1703 } 1704 1705 VibratorToken v; 1706 synchronized (mVibratorLock) { 1707 v = mVibratorTokens.get(token); 1708 if (v == null) { 1709 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++); 1710 try { 1711 token.linkToDeath(v, 0); 1712 } catch (RemoteException ex) { 1713 // give up 1714 throw new RuntimeException(ex); 1715 } 1716 mVibratorTokens.put(token, v); 1717 } 1718 } 1719 1720 synchronized (v) { 1721 v.mVibrating = true; 1722 nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue); 1723 } 1724 } 1725 1726 // Binder call 1727 @Override cancelVibrate(int deviceId, IBinder token)1728 public void cancelVibrate(int deviceId, IBinder token) { 1729 VibratorToken v; 1730 synchronized (mVibratorLock) { 1731 v = mVibratorTokens.get(token); 1732 if (v == null || v.mDeviceId != deviceId) { 1733 return; // nothing to cancel 1734 } 1735 } 1736 1737 cancelVibrateIfNeeded(v); 1738 } 1739 onVibratorTokenDied(VibratorToken v)1740 void onVibratorTokenDied(VibratorToken v) { 1741 synchronized (mVibratorLock) { 1742 mVibratorTokens.remove(v.mToken); 1743 } 1744 1745 cancelVibrateIfNeeded(v); 1746 } 1747 cancelVibrateIfNeeded(VibratorToken v)1748 private void cancelVibrateIfNeeded(VibratorToken v) { 1749 synchronized (v) { 1750 if (v.mVibrating) { 1751 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue); 1752 v.mVibrating = false; 1753 } 1754 } 1755 } 1756 1757 // Binder call 1758 @Override setPointerIconType(int iconId)1759 public void setPointerIconType(int iconId) { 1760 nativeSetPointerIconType(mPtr, iconId); 1761 } 1762 1763 // Binder call 1764 @Override setCustomPointerIcon(PointerIcon icon)1765 public void setCustomPointerIcon(PointerIcon icon) { 1766 Preconditions.checkNotNull(icon); 1767 nativeSetCustomPointerIcon(mPtr, icon); 1768 } 1769 1770 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1771 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1772 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1773 1774 pw.println("INPUT MANAGER (dumpsys input)\n"); 1775 String dumpStr = nativeDump(mPtr); 1776 if (dumpStr != null) { 1777 pw.println(dumpStr); 1778 } 1779 } 1780 checkCallingPermission(String permission, String func)1781 private boolean checkCallingPermission(String permission, String func) { 1782 // Quick check: if the calling permission is me, it's all okay. 1783 if (Binder.getCallingPid() == Process.myPid()) { 1784 return true; 1785 } 1786 1787 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { 1788 return true; 1789 } 1790 String msg = "Permission Denial: " + func + " from pid=" 1791 + Binder.getCallingPid() 1792 + ", uid=" + Binder.getCallingUid() 1793 + " requires " + permission; 1794 Slog.w(TAG, msg); 1795 return false; 1796 } 1797 1798 // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection). 1799 @Override monitor()1800 public void monitor() { 1801 synchronized (mInputFilterLock) { } 1802 nativeMonitor(mPtr); 1803 } 1804 1805 // Native callback. notifyConfigurationChanged(long whenNanos)1806 private void notifyConfigurationChanged(long whenNanos) { 1807 mWindowManagerCallbacks.notifyConfigurationChanged(); 1808 } 1809 1810 // Native callback. notifyInputDevicesChanged(InputDevice[] inputDevices)1811 private void notifyInputDevicesChanged(InputDevice[] inputDevices) { 1812 synchronized (mInputDevicesLock) { 1813 if (!mInputDevicesChangedPending) { 1814 mInputDevicesChangedPending = true; 1815 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED, 1816 mInputDevices).sendToTarget(); 1817 } 1818 1819 mInputDevices = inputDevices; 1820 } 1821 } 1822 1823 // Native callback. notifySwitch(long whenNanos, int switchValues, int switchMask)1824 private void notifySwitch(long whenNanos, int switchValues, int switchMask) { 1825 if (DEBUG) { 1826 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues) 1827 + ", mask=" + Integer.toHexString(switchMask)); 1828 } 1829 1830 if ((switchMask & SW_LID_BIT) != 0) { 1831 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); 1832 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen); 1833 } 1834 1835 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) { 1836 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0); 1837 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered); 1838 } 1839 1840 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) { 1841 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues, 1842 switchMask); 1843 } 1844 1845 if ((switchMask & SW_TABLET_MODE_BIT) != 0) { 1846 SomeArgs args = SomeArgs.obtain(); 1847 args.argi1 = (int) (whenNanos & 0xFFFFFFFF); 1848 args.argi2 = (int) (whenNanos >> 32); 1849 args.arg1 = Boolean.valueOf((switchValues & SW_TABLET_MODE_BIT) != 0); 1850 mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED, 1851 args).sendToTarget(); 1852 } 1853 1854 if ((switchMask & SW_MUTE_DEVICE_BIT) != 0) { 1855 final boolean micMute = ((switchValues & SW_MUTE_DEVICE_BIT) != 0); 1856 AudioManager audioManager = mContext.getSystemService(AudioManager.class); 1857 audioManager.setMicrophoneMuteFromSwitch(micMute); 1858 } 1859 } 1860 1861 // Native callback. notifyInputChannelBroken(IBinder token)1862 private void notifyInputChannelBroken(IBinder token) { 1863 mWindowManagerCallbacks.notifyInputChannelBroken(token); 1864 } 1865 1866 // Native callback notifyFocusChanged(IBinder oldToken, IBinder newToken)1867 private void notifyFocusChanged(IBinder oldToken, IBinder newToken) { 1868 if (mFocusedWindow != null) { 1869 if (mFocusedWindow.asBinder() == newToken) { 1870 Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow=" 1871 + mFocusedWindow); 1872 return; 1873 } 1874 setPointerCapture(false); 1875 } 1876 1877 mFocusedWindow = IWindow.Stub.asInterface(newToken); 1878 } 1879 1880 // Native callback. notifyANR(IBinder token, String reason)1881 private long notifyANR(IBinder token, String reason) { 1882 return mWindowManagerCallbacks.notifyANR( 1883 token, reason); 1884 } 1885 1886 // Native callback. filterInputEvent(InputEvent event, int policyFlags)1887 final boolean filterInputEvent(InputEvent event, int policyFlags) { 1888 synchronized (mInputFilterLock) { 1889 if (mInputFilter != null) { 1890 try { 1891 mInputFilter.filterInputEvent(event, policyFlags); 1892 } catch (RemoteException e) { 1893 /* ignore */ 1894 } 1895 return false; 1896 } 1897 } 1898 event.recycle(); 1899 return true; 1900 } 1901 1902 // Native callback. interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)1903 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 1904 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags); 1905 } 1906 1907 // Native callback. interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos, int policyFlags)1908 private int interceptMotionBeforeQueueingNonInteractive(int displayId, 1909 long whenNanos, int policyFlags) { 1910 return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive( 1911 displayId, whenNanos, policyFlags); 1912 } 1913 1914 // Native callback. interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags)1915 private long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) { 1916 return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags); 1917 } 1918 1919 // Native callback. dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags)1920 private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) { 1921 return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags); 1922 } 1923 1924 // Native callback. checkInjectEventsPermission(int injectorPid, int injectorUid)1925 private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) { 1926 return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS, 1927 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED; 1928 } 1929 1930 // Native callback. onPointerDownOutsideFocus(IBinder touchedToken)1931 private void onPointerDownOutsideFocus(IBinder touchedToken) { 1932 mWindowManagerCallbacks.onPointerDownOutsideFocus(touchedToken); 1933 } 1934 1935 // Native callback. getVirtualKeyQuietTimeMillis()1936 private int getVirtualKeyQuietTimeMillis() { 1937 return mContext.getResources().getInteger( 1938 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis); 1939 } 1940 1941 // Native callback. getExcludedDeviceNames()1942 private static String[] getExcludedDeviceNames() { 1943 List<String> names = new ArrayList<>(); 1944 // Read partner-provided list of excluded input devices 1945 // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". 1946 final File[] baseDirs = { 1947 Environment.getRootDirectory(), 1948 Environment.getVendorDirectory() 1949 }; 1950 for (File baseDir: baseDirs) { 1951 File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH); 1952 try { 1953 InputStream stream = new FileInputStream(confFile); 1954 names.addAll(ConfigurationProcessor.processExcludedDeviceNames(stream)); 1955 } catch (FileNotFoundException e) { 1956 // It's ok if the file does not exist. 1957 } catch (Exception e) { 1958 Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); 1959 } 1960 } 1961 return names.toArray(new String[0]); 1962 } 1963 1964 /** 1965 * Flatten a list of pairs into a list, with value positioned directly next to the key 1966 * @return Flattened list 1967 */ flatten(@onNull List<Pair<T, T>> pairs)1968 private static <T> List<T> flatten(@NonNull List<Pair<T, T>> pairs) { 1969 List<T> list = new ArrayList<>(pairs.size() * 2); 1970 for (Pair<T, T> pair : pairs) { 1971 list.add(pair.first); 1972 list.add(pair.second); 1973 } 1974 return list; 1975 } 1976 1977 /** 1978 * Ports are highly platform-specific, so only allow these to be specified in the vendor 1979 * directory. 1980 */ 1981 // Native callback getInputPortAssociations()1982 private static String[] getInputPortAssociations() { 1983 File baseDir = Environment.getVendorDirectory(); 1984 File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH); 1985 1986 try { 1987 InputStream stream = new FileInputStream(confFile); 1988 List<Pair<String, String>> associations = 1989 ConfigurationProcessor.processInputPortAssociations(stream); 1990 List<String> associationList = flatten(associations); 1991 return associationList.toArray(new String[0]); 1992 } catch (FileNotFoundException e) { 1993 // Most of the time, file will not exist, which is expected. 1994 } catch (Exception e) { 1995 Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e); 1996 } 1997 return new String[0]; 1998 } 1999 2000 /** 2001 * Gets if an input device could dispatch to the given display". 2002 * @param deviceId The input device id. 2003 * @param displayId The specific display id. 2004 * @return True if the device could dispatch to the given display, false otherwise. 2005 */ canDispatchToDisplay(int deviceId, int displayId)2006 public boolean canDispatchToDisplay(int deviceId, int displayId) { 2007 return nativeCanDispatchToDisplay(mPtr, deviceId, displayId); 2008 } 2009 2010 // Native callback. getKeyRepeatTimeout()2011 private int getKeyRepeatTimeout() { 2012 return ViewConfiguration.getKeyRepeatTimeout(); 2013 } 2014 2015 // Native callback. getKeyRepeatDelay()2016 private int getKeyRepeatDelay() { 2017 return ViewConfiguration.getKeyRepeatDelay(); 2018 } 2019 2020 // Native callback. getHoverTapTimeout()2021 private int getHoverTapTimeout() { 2022 return ViewConfiguration.getHoverTapTimeout(); 2023 } 2024 2025 // Native callback. getHoverTapSlop()2026 private int getHoverTapSlop() { 2027 return ViewConfiguration.getHoverTapSlop(); 2028 } 2029 2030 // Native callback. getDoubleTapTimeout()2031 private int getDoubleTapTimeout() { 2032 return ViewConfiguration.getDoubleTapTimeout(); 2033 } 2034 2035 // Native callback. getLongPressTimeout()2036 private int getLongPressTimeout() { 2037 return ViewConfiguration.getLongPressTimeout(); 2038 } 2039 2040 // Native callback. getPointerLayer()2041 private int getPointerLayer() { 2042 return mWindowManagerCallbacks.getPointerLayer(); 2043 } 2044 2045 // Native callback. getPointerIcon(int displayId)2046 private PointerIcon getPointerIcon(int displayId) { 2047 return PointerIcon.getDefaultIcon(getContextForDisplay(displayId)); 2048 } 2049 getContextForDisplay(int displayId)2050 private Context getContextForDisplay(int displayId) { 2051 if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) { 2052 return mDisplayContext; 2053 } 2054 2055 if (mContext.getDisplay().getDisplayId() == displayId) { 2056 mDisplayContext = mContext; 2057 return mDisplayContext; 2058 } 2059 2060 // Create and cache context for non-default display. 2061 final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); 2062 final Display display = displayManager.getDisplay(displayId); 2063 mDisplayContext = mContext.createDisplayContext(display); 2064 return mDisplayContext; 2065 } 2066 2067 // Native callback. getPointerDisplayId()2068 private int getPointerDisplayId() { 2069 return mWindowManagerCallbacks.getPointerDisplayId(); 2070 } 2071 2072 // Native callback. getKeyboardLayoutOverlay(InputDeviceIdentifier identifier)2073 private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) { 2074 if (!mSystemReady) { 2075 return null; 2076 } 2077 2078 String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier); 2079 if (keyboardLayoutDescriptor == null) { 2080 return null; 2081 } 2082 2083 final String[] result = new String[2]; 2084 visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() { 2085 @Override 2086 public void visitKeyboardLayout(Resources resources, 2087 int keyboardLayoutResId, KeyboardLayout layout) { 2088 try { 2089 result[0] = layout.getDescriptor(); 2090 result[1] = Streams.readFully(new InputStreamReader( 2091 resources.openRawResource(keyboardLayoutResId))); 2092 } catch (IOException ex) { 2093 } catch (NotFoundException ex) { 2094 } 2095 } 2096 }); 2097 if (result[0] == null) { 2098 Slog.w(TAG, "Could not get keyboard layout with descriptor '" 2099 + keyboardLayoutDescriptor + "'."); 2100 return null; 2101 } 2102 return result; 2103 } 2104 2105 // Native callback. getDeviceAlias(String uniqueId)2106 private String getDeviceAlias(String uniqueId) { 2107 if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) { 2108 // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId) 2109 return null; 2110 } 2111 return null; 2112 } 2113 2114 /** 2115 * Callback interface implemented by the Window Manager. 2116 */ 2117 public interface WindowManagerCallbacks { notifyConfigurationChanged()2118 public void notifyConfigurationChanged(); 2119 notifyLidSwitchChanged(long whenNanos, boolean lidOpen)2120 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen); 2121 notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered)2122 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered); 2123 notifyInputChannelBroken(IBinder token)2124 public void notifyInputChannelBroken(IBinder token); 2125 notifyANR(IBinder token, String reason)2126 public long notifyANR(IBinder token, String reason); 2127 interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)2128 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags); 2129 2130 /** 2131 * Provides an opportunity for the window manager policy to intercept early motion event 2132 * processing when the device is in a non-interactive state since these events are normally 2133 * dropped. 2134 */ interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos, int policyFlags)2135 int interceptMotionBeforeQueueingNonInteractive(int displayId, long whenNanos, 2136 int policyFlags); 2137 interceptKeyBeforeDispatching(IBinder token, KeyEvent event, int policyFlags)2138 public long interceptKeyBeforeDispatching(IBinder token, 2139 KeyEvent event, int policyFlags); 2140 dispatchUnhandledKey(IBinder token, KeyEvent event, int policyFlags)2141 public KeyEvent dispatchUnhandledKey(IBinder token, 2142 KeyEvent event, int policyFlags); 2143 getPointerLayer()2144 public int getPointerLayer(); 2145 getPointerDisplayId()2146 public int getPointerDisplayId(); 2147 2148 /** 2149 * Notifies window manager that a {@link android.view.MotionEvent#ACTION_DOWN} pointer event 2150 * occurred on a window that did not have focus. 2151 * 2152 * @param touchedToken The token for the window that received the input event. 2153 */ onPointerDownOutsideFocus(IBinder touchedToken)2154 void onPointerDownOutsideFocus(IBinder touchedToken); 2155 } 2156 2157 /** 2158 * Callback interface implemented by WiredAccessoryObserver. 2159 */ 2160 public interface WiredAccessoryCallbacks { notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask)2161 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask); systemReady()2162 public void systemReady(); 2163 } 2164 2165 /** 2166 * Private handler for the input manager. 2167 */ 2168 private final class InputManagerHandler extends Handler { InputManagerHandler(Looper looper)2169 public InputManagerHandler(Looper looper) { 2170 super(looper, null, true /*async*/); 2171 } 2172 2173 @Override handleMessage(Message msg)2174 public void handleMessage(Message msg) { 2175 switch (msg.what) { 2176 case MSG_DELIVER_INPUT_DEVICES_CHANGED: 2177 deliverInputDevicesChanged((InputDevice[])msg.obj); 2178 break; 2179 case MSG_SWITCH_KEYBOARD_LAYOUT: 2180 handleSwitchKeyboardLayout(msg.arg1, msg.arg2); 2181 break; 2182 case MSG_RELOAD_KEYBOARD_LAYOUTS: 2183 reloadKeyboardLayouts(); 2184 break; 2185 case MSG_UPDATE_KEYBOARD_LAYOUTS: 2186 updateKeyboardLayouts(); 2187 break; 2188 case MSG_RELOAD_DEVICE_ALIASES: 2189 reloadDeviceAliases(); 2190 break; 2191 case MSG_DELIVER_TABLET_MODE_CHANGED: 2192 SomeArgs args = (SomeArgs) msg.obj; 2193 long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32); 2194 boolean inTabletMode = (boolean) args.arg1; 2195 deliverTabletModeChanged(whenNanos, inTabletMode); 2196 break; 2197 } 2198 } 2199 } 2200 2201 /** 2202 * Hosting interface for input filters to call back into the input manager. 2203 */ 2204 private final class InputFilterHost extends IInputFilterHost.Stub { 2205 private boolean mDisconnected; 2206 disconnectLocked()2207 public void disconnectLocked() { 2208 mDisconnected = true; 2209 } 2210 2211 @Override sendInputEvent(InputEvent event, int policyFlags)2212 public void sendInputEvent(InputEvent event, int policyFlags) { 2213 if (event == null) { 2214 throw new IllegalArgumentException("event must not be null"); 2215 } 2216 2217 synchronized (mInputFilterLock) { 2218 if (!mDisconnected) { 2219 nativeInjectInputEvent(mPtr, event, 0, 0, 2220 InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0, 2221 policyFlags | WindowManagerPolicy.FLAG_FILTERED); 2222 } 2223 } 2224 } 2225 } 2226 2227 /** 2228 * Interface for the system to handle request from InputMonitors. 2229 */ 2230 private final class InputMonitorHost extends IInputMonitorHost.Stub { 2231 private final InputChannel mInputChannel; 2232 InputMonitorHost(InputChannel channel)2233 InputMonitorHost(InputChannel channel) { 2234 mInputChannel = channel; 2235 } 2236 2237 @Override pilferPointers()2238 public void pilferPointers() { 2239 nativePilferPointers(mPtr, asBinder()); 2240 } 2241 2242 @Override dispose()2243 public void dispose() { 2244 nativeUnregisterInputChannel(mPtr, mInputChannel); 2245 mInputChannel.dispose(); 2246 } 2247 } 2248 2249 private static final class KeyboardLayoutDescriptor { 2250 public String packageName; 2251 public String receiverName; 2252 public String keyboardLayoutName; 2253 format(String packageName, String receiverName, String keyboardName)2254 public static String format(String packageName, 2255 String receiverName, String keyboardName) { 2256 return packageName + "/" + receiverName + "/" + keyboardName; 2257 } 2258 parse(String descriptor)2259 public static KeyboardLayoutDescriptor parse(String descriptor) { 2260 int pos = descriptor.indexOf('/'); 2261 if (pos < 0 || pos + 1 == descriptor.length()) { 2262 return null; 2263 } 2264 int pos2 = descriptor.indexOf('/', pos + 1); 2265 if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) { 2266 return null; 2267 } 2268 2269 KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor(); 2270 result.packageName = descriptor.substring(0, pos); 2271 result.receiverName = descriptor.substring(pos + 1, pos2); 2272 result.keyboardLayoutName = descriptor.substring(pos2 + 1); 2273 return result; 2274 } 2275 } 2276 2277 private interface KeyboardLayoutVisitor { visitKeyboardLayout(Resources resources, int keyboardLayoutResId, KeyboardLayout layout)2278 void visitKeyboardLayout(Resources resources, 2279 int keyboardLayoutResId, KeyboardLayout layout); 2280 } 2281 2282 private final class InputDevicesChangedListenerRecord implements DeathRecipient { 2283 private final int mPid; 2284 private final IInputDevicesChangedListener mListener; 2285 InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener)2286 public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) { 2287 mPid = pid; 2288 mListener = listener; 2289 } 2290 2291 @Override binderDied()2292 public void binderDied() { 2293 if (DEBUG) { 2294 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died."); 2295 } 2296 onInputDevicesChangedListenerDied(mPid); 2297 } 2298 notifyInputDevicesChanged(int[] info)2299 public void notifyInputDevicesChanged(int[] info) { 2300 try { 2301 mListener.onInputDevicesChanged(info); 2302 } catch (RemoteException ex) { 2303 Slog.w(TAG, "Failed to notify process " 2304 + mPid + " that input devices changed, assuming it died.", ex); 2305 binderDied(); 2306 } 2307 } 2308 } 2309 2310 private final class TabletModeChangedListenerRecord implements DeathRecipient { 2311 private final int mPid; 2312 private final ITabletModeChangedListener mListener; 2313 TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener)2314 public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) { 2315 mPid = pid; 2316 mListener = listener; 2317 } 2318 2319 @Override binderDied()2320 public void binderDied() { 2321 if (DEBUG) { 2322 Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died."); 2323 } 2324 onTabletModeChangedListenerDied(mPid); 2325 } 2326 notifyTabletModeChanged(long whenNanos, boolean inTabletMode)2327 public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) { 2328 try { 2329 mListener.onTabletModeChanged(whenNanos, inTabletMode); 2330 } catch (RemoteException ex) { 2331 Slog.w(TAG, "Failed to notify process " + mPid + 2332 " that tablet mode changed, assuming it died.", ex); 2333 binderDied(); 2334 } 2335 } 2336 } 2337 2338 private final class VibratorToken implements DeathRecipient { 2339 public final int mDeviceId; 2340 public final IBinder mToken; 2341 public final int mTokenValue; 2342 2343 public boolean mVibrating; 2344 VibratorToken(int deviceId, IBinder token, int tokenValue)2345 public VibratorToken(int deviceId, IBinder token, int tokenValue) { 2346 mDeviceId = deviceId; 2347 mToken = token; 2348 mTokenValue = tokenValue; 2349 } 2350 2351 @Override binderDied()2352 public void binderDied() { 2353 if (DEBUG) { 2354 Slog.d(TAG, "Vibrator token died."); 2355 } 2356 onVibratorTokenDied(this); 2357 } 2358 } 2359 2360 private final class LocalService extends InputManagerInternal { 2361 @Override setDisplayViewports(List<DisplayViewport> viewports)2362 public void setDisplayViewports(List<DisplayViewport> viewports) { 2363 setDisplayViewportsInternal(viewports); 2364 } 2365 2366 @Override injectInputEvent(InputEvent event, int mode)2367 public boolean injectInputEvent(InputEvent event, int mode) { 2368 return injectInputEventInternal(event, mode); 2369 } 2370 2371 @Override setInteractive(boolean interactive)2372 public void setInteractive(boolean interactive) { 2373 nativeSetInteractive(mPtr, interactive); 2374 } 2375 2376 @Override toggleCapsLock(int deviceId)2377 public void toggleCapsLock(int deviceId) { 2378 nativeToggleCapsLock(mPtr, deviceId); 2379 } 2380 2381 @Override setPulseGestureEnabled(boolean enabled)2382 public void setPulseGestureEnabled(boolean enabled) { 2383 if (mDoubleTouchGestureEnableFile != null) { 2384 FileWriter writer = null; 2385 try { 2386 writer = new FileWriter(mDoubleTouchGestureEnableFile); 2387 writer.write(enabled ? "1" : "0"); 2388 } catch (IOException e) { 2389 Log.wtf(TAG, "Unable to setPulseGestureEnabled", e); 2390 } finally { 2391 IoUtils.closeQuietly(writer); 2392 } 2393 } 2394 } 2395 } 2396 } 2397