Merge changes from topic "keyLayoutAPI"

* changes:
  Add TestAPIs to test InputDevice#getKeyCodeForKeyLocation().
  Add API to get KeyCode produced by physical key location.
This commit is contained in:
Philip Junker
2022-01-24 18:39:18 +00:00
committed by Android (Google) Code Review
9 changed files with 154 additions and 29 deletions

View File

@@ -48689,6 +48689,7 @@ package android.view {
method public static int[] getDeviceIds();
method public int getId();
method public android.view.KeyCharacterMap getKeyCharacterMap();
method public int getKeyCodeForKeyLocation(int);
method public int getKeyboardType();
method @NonNull public android.hardware.lights.LightsManager getLightsManager();
method public android.view.InputDevice.MotionRange getMotionRange(int);

View File

@@ -38,6 +38,7 @@ package android {
field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
field public static final String REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL = "android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL";
field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS";
field public static final String SET_KEYBOARD_LAYOUT = "android.permission.SET_KEYBOARD_LAYOUT";
field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String TEST_BIOMETRIC = "android.permission.TEST_BIOMETRIC";
@@ -1180,9 +1181,23 @@ package android.hardware.hdmi {
package android.hardware.input {
public final class InputDeviceIdentifier implements android.os.Parcelable {
ctor public InputDeviceIdentifier(@NonNull String, int, int);
method public int describeContents();
method @NonNull public String getDescriptor();
method public int getProductId();
method public int getVendorId();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.InputDeviceIdentifier> CREATOR;
}
public final class InputManager {
method public int getBlockUntrustedTouchesMode(@NonNull android.content.Context);
method @Nullable public String getCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier);
method @NonNull public java.util.List<java.lang.String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull android.view.InputDevice);
method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setBlockUntrustedTouchesMode(@NonNull android.content.Context, int);
method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void setCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setMaximumObscuringOpacityForTouch(@FloatRange(from=0, to=1) float);
field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL
}
@@ -2740,6 +2755,7 @@ package android.view {
public final class InputDevice implements android.os.Parcelable {
method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void disable();
method @RequiresPermission("android.permission.DISABLE_INPUT_DEVICE") public void enable();
method @NonNull public android.hardware.input.InputDeviceIdentifier getIdentifier();
}
public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {

View File

@@ -50,6 +50,10 @@ interface IInputManager {
// Reports whether the hardware supports the given keys; returns true if successful
boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);
// Returns the keyCode produced when pressing the key at the specified location, given the
// active keyboard layout.
int getKeyCodeForKeyLocation(int deviceId, in int locationKeyCode);
// Temporarily changes the pointer speed.
void tryPointerSpeed(int speed);

View File

@@ -16,7 +16,9 @@
package android.hardware.input;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -28,12 +30,13 @@ import java.util.Objects;
*
* @hide
*/
@TestApi
public final class InputDeviceIdentifier implements Parcelable {
private final String mDescriptor;
private final int mVendorId;
private final int mProductId;
public InputDeviceIdentifier(String descriptor, int vendorId, int productId) {
public InputDeviceIdentifier(@NonNull String descriptor, int vendorId, int productId) {
this.mDescriptor = descriptor;
this.mVendorId = vendorId;
this.mProductId = productId;
@@ -51,12 +54,13 @@ public final class InputDeviceIdentifier implements Parcelable {
}
@Override
public void writeToParcel(Parcel dest, int flags) {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mDescriptor);
dest.writeInt(mVendorId);
dest.writeInt(mProductId);
}
@NonNull
public String getDescriptor() {
return mDescriptor;
}

View File

@@ -58,6 +58,7 @@ import android.util.SparseArray;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputMonitor;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VerifiedInputEvent;
@@ -636,6 +637,30 @@ public final class InputManager {
}
}
/**
* Returns the descriptors of all supported keyboard layouts appropriate for the specified
* input device.
* <p>
* The input manager consults the built-in keyboard layouts as well as all keyboard layouts
* advertised by applications using a {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
* </p>
*
* @param device The input device to query.
* @return The ids of all keyboard layouts which are supported by the specified input device.
*
* @hide
*/
@TestApi
@NonNull
public List<String> getKeyboardLayoutDescriptorsForInputDevice(@NonNull InputDevice device) {
KeyboardLayout[] layouts = getKeyboardLayoutsForInputDevice(device.getIdentifier());
List<String> res = new ArrayList<>();
for (KeyboardLayout kl : layouts) {
res.add(kl.getDescriptor());
}
return res;
}
/**
* Gets information about all supported keyboard layouts appropriate
* for a specific input device.
@@ -650,7 +675,9 @@ public final class InputManager {
*
* @hide
*/
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
@NonNull
public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
@NonNull InputDeviceIdentifier identifier) {
try {
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
@@ -680,15 +707,17 @@ public final class InputManager {
}
/**
* Gets the current keyboard layout descriptor for the specified input
* device.
* Gets the current keyboard layout descriptor for the specified input device.
*
* @param identifier Identifier for the input device
* @return The keyboard layout descriptor, or null if no keyboard layout has
* been set.
* @return The keyboard layout descriptor, or null if no keyboard layout has been set.
*
* @hide
*/
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
@TestApi
@Nullable
public String getCurrentKeyboardLayoutForInputDevice(
@NonNull InputDeviceIdentifier identifier) {
try {
return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
} catch (RemoteException ex) {
@@ -697,20 +726,21 @@ public final class InputManager {
}
/**
* Sets the current keyboard layout descriptor for the specified input
* device.
* Sets the current keyboard layout descriptor for the specified input device.
* <p>
* This method may have the side-effect of causing the input device in
* question to be reconfigured.
* This method may have the side-effect of causing the input device in question to be
* reconfigured.
* </p>
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The keyboard layout descriptor to use,
* must not be null.
* @param keyboardLayoutDescriptor The keyboard layout descriptor to use, must not be null.
*
* @hide
*/
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
@TestApi
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void setCurrentKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
@NonNull String keyboardLayoutDescriptor) {
if (identifier == null) {
throw new IllegalArgumentException("identifier must not be null");
}
@@ -727,11 +757,11 @@ public final class InputManager {
}
/**
* Gets all keyboard layout descriptors that are enabled for the specified
* input device.
* Gets all keyboard layout descriptors that are enabled for the specified input device.
*
* @param identifier The identifier for the input device.
* @return The keyboard layout descriptors.
*
* @hide
*/
public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
@@ -749,15 +779,16 @@ public final class InputManager {
/**
* Adds the keyboard layout descriptor for the specified input device.
* <p>
* This method may have the side-effect of causing the input device in
* question to be reconfigured.
* This method may have the side-effect of causing the input device in question to be
* reconfigured.
* </p>
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
* add.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to add.
*
* @hide
*/
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (identifier == null) {
@@ -777,17 +808,19 @@ public final class InputManager {
/**
* Removes the keyboard layout descriptor for the specified input device.
* <p>
* This method may have the side-effect of causing the input device in
* question to be reconfigured.
* This method may have the side-effect of causing the input device in question to be
* reconfigured.
* </p>
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
* remove.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to remove.
*
* @hide
*/
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
@TestApi
@RequiresPermission(Manifest.permission.SET_KEYBOARD_LAYOUT)
public void removeKeyboardLayoutForInputDevice(@NonNull InputDeviceIdentifier identifier,
@NonNull String keyboardLayoutDescriptor) {
if (identifier == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
@@ -1044,6 +1077,27 @@ public final class InputManager {
return ret;
}
/**
* Gets the key code produced by the specified location on a US keyboard layout.
* Key code as defined in {@link android.view.KeyEvent}.
* This API is only functional for devices with {@link InputDevice#SOURCE_KEYBOARD} available
* which can alter their key mapping using country specific keyboard layouts.
*
* @param deviceId The input device id.
* @param locationKeyCode The location of a key on a US keyboard layout.
* @return The key code produced when pressing the key at the specified location, given the
* active keyboard layout. Returns {@link KeyEvent#KEYCODE_UNKNOWN} if the requested
* mapping could not be determined, or if an error occurred.
* @hide
*/
public int getKeyCodeForKeyLocation(int deviceId, int locationKeyCode) {
try {
return mIm.getKeyCodeForKeyLocation(deviceId, locationKeyCode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Injects an input event into the event system on behalf of an application.

View File

@@ -572,6 +572,8 @@ public final class InputDevice implements Parcelable {
* @return The identifier object for this device
* @hide
*/
@TestApi
@NonNull
public InputDeviceIdentifier getIdentifier() {
return mIdentifier;
}
@@ -734,6 +736,21 @@ public final class InputDevice implements Parcelable {
return InputManager.getInstance().deviceHasKeys(mId, keys);
}
/**
* Gets the key code produced by the specified location on a US keyboard layout.
* Key code as defined in {@link android.view.KeyEvent}.
* This API is only functional for devices with {@link InputDevice#SOURCE_KEYBOARD} available
* which can alter their key mapping using country specific keyboard layouts.
*
* @param locationKeyCode The location of a key on a US keyboard layout.
* @return The key code produced when pressing the key at the specified location, given the
* active keyboard layout. Returns {@link KeyEvent#KEYCODE_UNKNOWN} if the requested
* mapping could not be determined, or if an error occurred.
*/
public int getKeyCodeForKeyLocation(int locationKeyCode) {
return InputManager.getInstance().getKeyCodeForKeyLocation(mId, locationKeyCode);
}
/**
* Gets information about the range of values for a particular {@link MotionEvent} axis.
* If the device supports multiple sources, the same axis may have different meanings

View File

@@ -4251,7 +4251,8 @@
<!-- Allows low-level access to setting the keyboard layout.
<p>Not for use by third-party applications.
@hide -->
@hide
@TestApi -->
<permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
android:protectionLevel="signature" />

View File

@@ -16,6 +16,8 @@
package com.android.server.input;
import static android.view.KeyEvent.KEYCODE_UNKNOWN;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
@@ -289,6 +291,8 @@ public class InputManagerService extends IInputManager.Stub
int deviceId, int sourceMask, int sw);
private static native boolean nativeHasKeys(long ptr,
int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
private static native int nativeGetKeyCodeForKeyLocation(long ptr, int deviceId,
int locationKeyCode);
private static native InputChannel nativeCreateInputChannel(long ptr, String name);
private static native InputChannel nativeCreateInputMonitor(long ptr, int displayId,
boolean isGestureMonitor, String name, int pid);
@@ -665,6 +669,22 @@ public class InputManagerService extends IInputManager.Stub
return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
}
/**
* Returns the keyCode generated by the specified location on a US keyboard layout.
* This takes into consideration the currently active keyboard layout.
*
* @param deviceId The input device id.
* @param locationKeyCode The location of a key on a US keyboard layout.
* @return The KeyCode this physical key location produces.
*/
@Override // Binder call
public int getKeyCodeForKeyLocation(int deviceId, int locationKeyCode) {
if (locationKeyCode <= KEYCODE_UNKNOWN || locationKeyCode > KeyEvent.getMaxKeyCode()) {
return KEYCODE_UNKNOWN;
}
return nativeGetKeyCodeForKeyLocation(mPtr, deviceId, locationKeyCode);
}
/**
* Transfer the current touch gesture to the provided window.
*

View File

@@ -1586,6 +1586,13 @@ static jboolean nativeHasKeys(JNIEnv* env, jclass /* clazz */,
return result;
}
static jint nativeGetKeyCodeForKeyLocation(JNIEnv* env, jclass /* clazz */, jlong ptr,
jint deviceId, jint locationKeyCode) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
return (jint)im->getInputManager()->getReader().getKeyCodeForKeyLocation(deviceId,
locationKeyCode);
}
static void handleInputChannelDisposed(JNIEnv* env, jobject /* inputChannelObj */,
const std::shared_ptr<InputChannel>& inputChannel,
void* data) {
@@ -2337,6 +2344,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
{"nativeGetKeyCodeState", "(JIII)I", (void*)nativeGetKeyCodeState},
{"nativeGetSwitchState", "(JIII)I", (void*)nativeGetSwitchState},
{"nativeHasKeys", "(JII[I[Z)Z", (void*)nativeHasKeys},
{"nativeGetKeyCodeForKeyLocation", "(JII)I", (void*)nativeGetKeyCodeForKeyLocation},
{"nativeCreateInputChannel", "(JLjava/lang/String;)Landroid/view/InputChannel;",
(void*)nativeCreateInputChannel},
{"nativeCreateInputMonitor", "(JIZLjava/lang/String;I)Landroid/view/InputChannel;",