diff options
-rw-r--r-- | core/java/android/hardware/input/IInputManager.aidl | 11 | ||||
-rw-r--r-- | core/java/android/hardware/input/InputDeviceIdentifier.aidl | 19 | ||||
-rw-r--r-- | core/java/android/hardware/input/InputDeviceIdentifier.java | 82 | ||||
-rw-r--r-- | core/java/android/hardware/input/InputManager.java | 84 | ||||
-rw-r--r-- | core/java/android/view/InputDevice.java | 90 | ||||
-rw-r--r-- | libs/input/InputReader.cpp | 2 | ||||
-rw-r--r-- | libs/input/InputReader.h | 3 | ||||
-rw-r--r-- | libs/input/tests/InputReader_test.cpp | 2 | ||||
-rw-r--r-- | services/core/java/com/android/server/input/InputManagerService.java | 132 | ||||
-rw-r--r-- | services/core/jni/com_android_server_input_InputManagerService.cpp | 27 |
10 files changed, 312 insertions, 140 deletions
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl index 9b6f82a..f1e7e98 100644 --- a/core/java/android/hardware/input/IInputManager.aidl +++ b/core/java/android/hardware/input/IInputManager.aidl @@ -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. diff --git a/core/java/android/hardware/input/InputDeviceIdentifier.aidl b/core/java/android/hardware/input/InputDeviceIdentifier.aidl new file mode 100644 index 0000000..7234a91 --- /dev/null +++ b/core/java/android/hardware/input/InputDeviceIdentifier.aidl @@ -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; diff --git a/core/java/android/hardware/input/InputDeviceIdentifier.java b/core/java/android/hardware/input/InputDeviceIdentifier.java new file mode 100644 index 0000000..5e832e3 --- /dev/null +++ b/core/java/android/hardware/input/InputDeviceIdentifier.java @@ -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]; + } + + }; +} diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 30e69a6..a2aeafb 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -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); } diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index e829116..0b12cbe 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -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. @@ -441,6 +445,18 @@ public final class InputDevice implements Parcelable { } /** + * 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 * properties may have changed. @@ -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. diff --git a/libs/input/InputReader.cpp b/libs/input/InputReader.cpp index a683c4b..94e2a80 100644 --- a/libs/input/InputReader.cpp +++ b/libs/input/InputReader.cpp @@ -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(); } diff --git a/libs/input/InputReader.h b/libs/input/InputReader.h index e6f45b6..674f67d 100644 --- a/libs/input/InputReader.h +++ b/libs/input/InputReader.h @@ -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; diff --git a/libs/input/tests/InputReader_test.cpp b/libs/input/tests/InputReader_test.cpp index f068732..aaa973d 100644 --- a/libs/input/tests/InputReader_test.cpp +++ b/libs/input/tests/InputReader_test.cpp @@ -186,7 +186,7 @@ private: mInputDevices = inputDevices; } - virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor) { + virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) { return NULL; } diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 3145805..c3c22f6 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -46,6 +46,7 @@ import android.content.res.XmlResourceParser; import android.database.ContentObserver; import android.hardware.input.IInputDevicesChangedListener; import android.hardware.input.IInputManager; +import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.hardware.input.KeyboardLayout; import android.os.Binder; @@ -378,7 +379,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. @@ -413,10 +414,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. @@ -426,7 +427,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 @@ -444,10 +445,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. @@ -456,7 +457,7 @@ public class InputManagerService extends IInputManager.Stub if (inputChannel == null) { throw new IllegalArgumentException("inputChannel must not be null."); } - + nativeUnregisterInputChannel(mPtr, inputChannel); } @@ -894,35 +895,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 { @@ -932,36 +960,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 { @@ -971,26 +1002,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 { @@ -1007,14 +1043,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(); } @@ -1042,11 +1079,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); } @@ -1426,13 +1463,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; } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 4ab2086..12a1c7a 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -99,6 +99,12 @@ static struct { jclass clazz; } gMotionEventClassInfo; +static struct { + jclass clazz; + jmethodID constructor; +} gInputDeviceIdentifierInfo; + + // --- Global functions --- @@ -183,7 +189,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 --- */ @@ -492,13 +498,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))); @@ -1438,7 +1447,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;"); @@ -1458,6 +1468,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; } |