b/12068020 Make kb layouts only unique to vendor/product. Do not merge

This is a cherry-pick of https://googleplex-android-review.git.corp.google.com/#/c/399886/

Instead of storing a kb layout per device descriptor (which is expected
to be unique), store it for each vendor/product. This way we can keep
a consistent layout between identical but physically different keyboards.

There are some corner cases this is expected to fail on, namely devices
that incorrectly have the same vendor/product id. Devices that don't
define a vendor/product id will continue to use the descriptor to store
layout files.

Change-Id: I1f2508561992080459310d5a644dad65a9c24f1a
This commit is contained in:
RoboErik
2013-12-16 11:27:55 -08:00
parent c1e0015ec3
commit ca9eef6203
10 changed files with 312 additions and 140 deletions

View File

@@ -16,6 +16,7 @@
package android.hardware.input;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
import android.os.IBinder;
@@ -41,13 +42,13 @@ interface IInputManager {
// Keyboard layouts configuration.
KeyboardLayout[] getKeyboardLayouts();
KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
String getCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
void setCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
String[] getKeyboardLayoutsForInputDevice(String inputDeviceDescriptor);
void addKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
String[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
void removeKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor);
// Registers an input devices changed listener.

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.input;
parcelable InputDeviceIdentifier;

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.input;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Wrapper for passing identifying information for input devices.
*
* @hide
*/
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) {
this.mDescriptor = descriptor;
this.mVendorId = vendorId;
this.mProductId = productId;
}
private InputDeviceIdentifier(Parcel src) {
mDescriptor = src.readString();
mVendorId = src.readInt();
mProductId = src.readInt();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mDescriptor);
dest.writeInt(mVendorId);
dest.writeInt(mProductId);
}
public String getDescriptor() {
return mDescriptor;
}
public int getVendorId() {
return mVendorId;
}
public int getProductId() {
return mProductId;
}
public static final Parcelable.Creator<InputDeviceIdentifier> CREATOR =
new Parcelable.Creator<InputDeviceIdentifier>() {
@Override
public InputDeviceIdentifier createFromParcel(Parcel source) {
return new InputDeviceIdentifier(source);
}
@Override
public InputDeviceIdentifier[] newArray(int size) {
return new InputDeviceIdentifier[size];
}
};
}

View File

@@ -26,6 +26,8 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Vibrator;
@@ -373,20 +375,17 @@ public final class InputManager {
}
/**
* Gets the current keyboard layout descriptor for the specified input device.
*
* @param inputDeviceDescriptor The input device descriptor.
* @return The keyboard layout descriptor, or null if no keyboard layout has been set.
* 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.
* @hide
*/
public String getCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
try {
return mIm.getCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor);
return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
} catch (RemoteException ex) {
Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
return null;
@@ -394,28 +393,29 @@ 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 inputDeviceDescriptor The input device descriptor.
* @param keyboardLayoutDescriptor The keyboard layout descriptor to use, must not be null.
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The keyboard layout descriptor to use,
* must not be null.
* @hide
*/
public void setCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
if (identifier == null) {
throw new IllegalArgumentException("identifier must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
try {
mIm.setCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor,
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
} catch (RemoteException ex) {
Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
@@ -423,20 +423,20 @@ 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 inputDeviceDescriptor The input device descriptor.
* @param identifier The identifier for the input device.
* @return The keyboard layout descriptors.
*
* @hide
*/
public String[] getKeyboardLayoutsForInputDevice(String inputDeviceDescriptor) {
if (inputDeviceDescriptor == null) {
public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
if (identifier == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
try {
return mIm.getKeyboardLayoutsForInputDevice(inputDeviceDescriptor);
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
return ArrayUtils.emptyArray(String.class);
@@ -446,18 +446,18 @@ 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 inputDeviceDescriptor The input device descriptor.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to add.
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
* add.
* @hide
*/
public void addKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (inputDeviceDescriptor == null) {
if (identifier == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
if (keyboardLayoutDescriptor == null) {
@@ -465,7 +465,7 @@ public final class InputManager {
}
try {
mIm.addKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
Log.w(TAG, "Could not add keyboard layout for input device.", ex);
}
@@ -474,18 +474,18 @@ 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 inputDeviceDescriptor The input device descriptor.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to remove.
*
* @param identifier The identifier for the input device.
* @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
* remove.
* @hide
*/
public void removeKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (inputDeviceDescriptor == null) {
if (identifier == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
if (keyboardLayoutDescriptor == null) {
@@ -493,7 +493,7 @@ public final class InputManager {
}
try {
mIm.removeKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
}

View File

@@ -17,6 +17,7 @@
package android.view;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.os.Parcel;
import android.os.Parcelable;
@@ -49,6 +50,7 @@ public final class InputDevice implements Parcelable {
private final int mVendorId;
private final int mProductId;
private final String mDescriptor;
private final InputDeviceIdentifier mIdentifier;
private final boolean mIsExternal;
private final int mSources;
private final int mKeyboardType;
@@ -61,7 +63,7 @@ public final class InputDevice implements Parcelable {
/**
* A mask for input source classes.
*
*
* Each distinct input source constant has one or more input source class bits set to
* specify the desired interpretation for its input events.
*/
@@ -77,46 +79,46 @@ public final class InputDevice implements Parcelable {
/**
* The input source has buttons or keys.
* Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
*
*
* A {@link KeyEvent} should be interpreted as a button or key press.
*
*
* Use {@link #getKeyCharacterMap} to query the device's button and key mappings.
*/
public static final int SOURCE_CLASS_BUTTON = 0x00000001;
/**
* The input source is a pointing device associated with a display.
* Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
*
*
* A {@link MotionEvent} should be interpreted as absolute coordinates in
* display units according to the {@link View} hierarchy. Pointer down/up indicated when
* the finger touches the display or when the selection button is pressed/released.
*
*
* Use {@link #getMotionRange} to query the range of the pointing device. Some devices permit
* touches outside the display area so the effective range may be somewhat smaller or larger
* than the actual display size.
*/
public static final int SOURCE_CLASS_POINTER = 0x00000002;
/**
* The input source is a trackball navigation device.
* Examples: {@link #SOURCE_TRACKBALL}.
*
*
* A {@link MotionEvent} should be interpreted as relative movements in device-specific
* units used for navigation purposes. Pointer down/up indicates when the selection button
* is pressed/released.
*
*
* Use {@link #getMotionRange} to query the range of motion.
*/
public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
/**
* The input source is an absolute positioning device not associated with a display
* (unlike {@link #SOURCE_CLASS_POINTER}).
*
*
* A {@link MotionEvent} should be interpreted as absolute coordinates in
* device-specific surface units.
*
*
* Use {@link #getMotionRange} to query the range of positions.
*/
public static final int SOURCE_CLASS_POSITION = 0x00000008;
@@ -134,7 +136,7 @@ public final class InputDevice implements Parcelable {
* The input source is unknown.
*/
public static final int SOURCE_UNKNOWN = 0x00000000;
/**
* The input source is a keyboard.
*
@@ -145,10 +147,10 @@ public final class InputDevice implements Parcelable {
* @see #SOURCE_CLASS_BUTTON
*/
public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
/**
* The input source is a DPad.
*
*
* @see #SOURCE_CLASS_BUTTON
*/
public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
@@ -163,16 +165,16 @@ public final class InputDevice implements Parcelable {
/**
* The input source is a touch screen pointing device.
*
*
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
/**
* The input source is a mouse pointing device.
* This code is also used for other mouse-like pointing devices such as trackpads
* and trackpoints.
*
*
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
@@ -199,15 +201,15 @@ public final class InputDevice implements Parcelable {
/**
* The input source is a trackball.
*
*
* @see #SOURCE_CLASS_TRACKBALL
*/
public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
/**
* The input source is a touch pad or digitizer tablet that is not
* associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
*
*
* @see #SOURCE_CLASS_POSITION
*/
public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
@@ -239,7 +241,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_X} instead.
*/
@@ -248,7 +250,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_Y} instead.
*/
@@ -257,7 +259,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
*/
@@ -266,7 +268,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
*/
@@ -275,7 +277,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
*/
@@ -284,7 +286,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
*/
@@ -293,7 +295,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
*/
@@ -302,7 +304,7 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
*/
@@ -311,24 +313,24 @@ public final class InputDevice implements Parcelable {
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
*
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
*/
@Deprecated
public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
/**
* There is no keyboard.
*/
public static final int KEYBOARD_TYPE_NONE = 0;
/**
* The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment
* of buttons that are not mapped as alphabetic keys suitable for text input.
*/
public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
/**
* The keyboard supports a complement of alphabetic keys.
*/
@@ -361,6 +363,7 @@ public final class InputDevice implements Parcelable {
mKeyCharacterMap = keyCharacterMap;
mHasVibrator = hasVibrator;
mHasButtonUnderPad = hasButtonUnderPad;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
private InputDevice(Parcel in) {
@@ -377,6 +380,7 @@ public final class InputDevice implements Parcelable {
mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mHasVibrator = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
for (;;) {
int axis = in.readInt();
@@ -396,7 +400,7 @@ public final class InputDevice implements Parcelable {
public static InputDevice getDevice(int id) {
return InputManager.getInstance().getInputDevice(id);
}
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
@@ -440,6 +444,18 @@ public final class InputDevice implements Parcelable {
return mControllerNumber;
}
/**
* The set of identifying information for type of input device. This
* information can be used by the system to configure appropriate settings
* for the device.
*
* @return The identifier object for this device
* @hide
*/
public InputDeviceIdentifier getIdentifier() {
return mIdentifier;
}
/**
* Gets a generation number for this input device.
* The generation number is incremented whenever the device is reconfigured and its
@@ -553,7 +569,7 @@ public final class InputDevice implements Parcelable {
public String getName() {
return mName;
}
/**
* Gets the input sources supported by this input device as a combined bitfield.
* @return The supported input sources.
@@ -561,7 +577,7 @@ public final class InputDevice implements Parcelable {
public int getSources() {
return mSources;
}
/**
* Gets the keyboard type.
* @return The keyboard type.
@@ -569,7 +585,7 @@ public final class InputDevice implements Parcelable {
public int getKeyboardType() {
return mKeyboardType;
}
/**
* Gets the key character map associated with this input device.
* @return The key character map.

View File

@@ -911,7 +911,7 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
sp<KeyCharacterMap> keyboardLayout =
mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor);
mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
bumpGeneration();
}

View File

@@ -281,7 +281,8 @@ public:
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
/* Gets the keyboard layout for a particular input device. */
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) = 0;
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(
const InputDeviceIdentifier& identifier) = 0;
/* Gets a user-supplied alias for a particular input device, or an empty string if none. */
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;

View File

@@ -186,7 +186,7 @@ private:
mInputDevices = inputDevices;
}
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) {
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) {
return NULL;
}

View File

@@ -48,6 +48,7 @@ import android.database.ContentObserver;
import android.hardware.display.DisplayViewport;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.KeyboardLayout;
@@ -382,7 +383,7 @@ public class InputManagerService extends IInputManager.Stub
public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
}
/**
* Gets the current state of a switch by switch code.
* @param deviceId The input device id, or -1 to consult all devices.
@@ -417,10 +418,10 @@ public class InputManagerService extends IInputManager.Stub
throw new IllegalArgumentException("keyExists must not be null and must be at "
+ "least as large as keyCodes.");
}
return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
}
/**
* Creates an input channel that will receive all input from the input dispatcher.
* @param inputChannelName The input channel name.
@@ -430,7 +431,7 @@ public class InputManagerService extends IInputManager.Stub
if (inputChannelName == null) {
throw new IllegalArgumentException("inputChannelName must not be null.");
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
inputChannels[0].dispose(); // don't need to retain the Java object reference
@@ -448,10 +449,10 @@ public class InputManagerService extends IInputManager.Stub
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
/**
* Unregisters an input channel.
* @param inputChannel The input channel to unregister.
@@ -460,7 +461,7 @@ public class InputManagerService extends IInputManager.Stub
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeUnregisterInputChannel(mPtr, inputChannel);
}
@@ -902,35 +903,62 @@ public class InputManagerService extends IInputManager.Stub
}
}
@Override // Binder call
public String getCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
/**
* Builds a layout descriptor for the vendor/product. This returns the
* descriptor for ids that aren't useful (such as the default 0, 0).
*/
private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
if (identifier == null || identifier.getDescriptor() == null) {
throw new IllegalArgumentException("identifier and descriptor must not be null");
}
if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
return identifier.getDescriptor();
}
StringBuilder bob = new StringBuilder();
bob.append("vendor:").append(identifier.getVendorId());
bob.append(",product:").append(identifier.getProductId());
return bob.toString();
}
@Override // Binder call
public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
return mDataStore.getCurrentKeyboardLayout(inputDeviceDescriptor);
String layout = null;
// try loading it using the layout descriptor if we have it
layout = mDataStore.getCurrentKeyboardLayout(key);
if (layout == null && !key.equals(identifier.getDescriptor())) {
// if it doesn't exist fall back to the device descriptor
layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
}
if (DEBUG) {
Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
+ layout);
}
return layout;
}
}
@Override // Binder call
public void setCurrentKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
"setCurrentKeyboardLayoutForInputDevice()")) {
throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
}
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
try {
if (mDataStore.setCurrentKeyboardLayout(
inputDeviceDescriptor, keyboardLayoutDescriptor)) {
if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
if (DEBUG) {
Slog.d(TAG, "Saved keyboard layout using " + key);
}
mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
}
} finally {
@@ -940,36 +968,39 @@ public class InputManagerService extends IInputManager.Stub
}
@Override // Binder call
public String[] getKeyboardLayoutsForInputDevice(String inputDeviceDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
return mDataStore.getKeyboardLayouts(inputDeviceDescriptor);
String[] layouts = mDataStore.getKeyboardLayouts(key);
if ((layouts == null || layouts.length == 0)
&& !key.equals(identifier.getDescriptor())) {
layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
}
return layouts;
}
}
@Override // Binder call
public void addKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
"addKeyboardLayoutForInputDevice()")) {
throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
}
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
try {
String oldLayout = mDataStore.getCurrentKeyboardLayout(inputDeviceDescriptor);
if (mDataStore.addKeyboardLayout(inputDeviceDescriptor, keyboardLayoutDescriptor)
String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
}
if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
&& !Objects.equal(oldLayout,
mDataStore.getCurrentKeyboardLayout(inputDeviceDescriptor))) {
mDataStore.getCurrentKeyboardLayout(key))) {
mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
}
} finally {
@@ -979,26 +1010,31 @@ public class InputManagerService extends IInputManager.Stub
}
@Override // Binder call
public void removeKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
String keyboardLayoutDescriptor) {
if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
"removeKeyboardLayoutForInputDevice()")) {
throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
}
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
if (keyboardLayoutDescriptor == null) {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
String key = getLayoutDescriptor(identifier);
synchronized (mDataStore) {
try {
String oldLayout = mDataStore.getCurrentKeyboardLayout(inputDeviceDescriptor);
if (mDataStore.removeKeyboardLayout(inputDeviceDescriptor,
keyboardLayoutDescriptor)
&& !Objects.equal(oldLayout,
mDataStore.getCurrentKeyboardLayout(inputDeviceDescriptor))) {
String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
}
boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
if (!key.equals(identifier.getDescriptor())) {
// We need to remove from both places to ensure it is gone
removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
keyboardLayoutDescriptor);
}
if (removed && !Objects.equal(oldLayout,
mDataStore.getCurrentKeyboardLayout(key))) {
mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
}
} finally {
@@ -1015,14 +1051,15 @@ public class InputManagerService extends IInputManager.Stub
private void handleSwitchKeyboardLayout(int deviceId, int direction) {
final InputDevice device = getInputDevice(deviceId);
if (device != null) {
final String inputDeviceDescriptor = device.getDescriptor();
final boolean changed;
final String keyboardLayoutDescriptor;
String key = getLayoutDescriptor(device.getIdentifier());
synchronized (mDataStore) {
try {
changed = mDataStore.switchKeyboardLayout(inputDeviceDescriptor, direction);
changed = mDataStore.switchKeyboardLayout(key, direction);
keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
inputDeviceDescriptor);
key);
} finally {
mDataStore.saveIfNeeded();
}
@@ -1050,11 +1087,11 @@ public class InputManagerService extends IInputManager.Stub
public void setInputWindows(InputWindowHandle[] windowHandles) {
nativeSetInputWindows(mPtr, windowHandles);
}
public void setFocusedApplication(InputApplicationHandle application) {
nativeSetFocusedApplication(mPtr, application);
}
public void setInputDispatchMode(boolean enabled, boolean frozen) {
nativeSetInputDispatchMode(mPtr, enabled, frozen);
}
@@ -1435,13 +1472,12 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
private String[] getKeyboardLayoutOverlay(String inputDeviceDescriptor) {
private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
if (!mSystemReady) {
return null;
}
String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(
inputDeviceDescriptor);
String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
if (keyboardLayoutDescriptor == null) {
return null;
}

View File

@@ -99,6 +99,12 @@ static struct {
jclass clazz;
} gMotionEventClassInfo;
static struct {
jclass clazz;
jmethodID constructor;
} gInputDeviceIdentifierInfo;
// --- Global functions ---
@@ -181,7 +187,7 @@ public:
virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor);
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -490,13 +496,16 @@ void NativeInputManager::notifyInputDevicesChanged(const Vector<InputDeviceInfo>
}
sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay(
const String8& inputDeviceDescriptor) {
const InputDeviceIdentifier& identifier) {
JNIEnv* env = jniEnv();
sp<KeyCharacterMap> result;
ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string()));
ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz,
gInputDeviceIdentifierInfo.constructor, descriptor.get(),
identifier.vendor, identifier.product));
ScopedLocalRef<jobjectArray> arrayObj(env, jobjectArray(env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getKeyboardLayoutOverlay, descriptorObj.get())));
gServiceClassInfo.getKeyboardLayoutOverlay, identifierObj.get())));
if (arrayObj.get()) {
ScopedLocalRef<jstring> filenameObj(env,
jstring(env->GetObjectArrayElement(arrayObj.get(), 0)));
@@ -1430,7 +1439,8 @@ int register_android_server_InputManager(JNIEnv* env) {
"getPointerIcon", "()Landroid/view/PointerIcon;");
GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
"getKeyboardLayoutOverlay", "(Ljava/lang/String;)[Ljava/lang/String;");
"getKeyboardLayoutOverlay",
"(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;");
GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
"getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
@@ -1450,6 +1460,13 @@ int register_android_server_InputManager(JNIEnv* env) {
FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
// InputDeviceIdentifier
FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier");
gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz));
GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz,
"<init>", "(Ljava/lang/String;II)V");
return 0;
}