summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ContextImpl.java6
-rw-r--r--core/java/android/app/Instrumentation.java8
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl8
-rwxr-xr-xcore/java/android/hardware/input/InputManager.java363
-rw-r--r--core/java/android/hardware/input/KeyboardLayout.aidl19
-rw-r--r--core/java/android/hardware/input/KeyboardLayout.java91
-rwxr-xr-xcore/java/android/view/InputDevice.java112
-rw-r--r--core/java/android/view/KeyCharacterMap.java87
8 files changed, 313 insertions, 381 deletions
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c5d7b91..138a88f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -325,9 +325,9 @@ class ContextImpl extends Context {
return createDropBoxManager();
}});
- registerService(INPUT_SERVICE, new ServiceFetcher() {
- public Object createService(ContextImpl ctx) {
- return new InputManager(ctx);
+ registerService(INPUT_SERVICE, new StaticServiceFetcher() {
+ public Object createStaticService() {
+ return InputManager.getInstance();
}});
registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index f955713..75c6e11 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -883,7 +883,7 @@ public class Instrumentation {
}
KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
- InputManager.injectInputEvent(newEvent,
+ InputManager.getInstance().injectInputEvent(newEvent,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
@@ -926,7 +926,8 @@ public class Instrumentation {
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
}
- InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
+ InputManager.getInstance().injectInputEvent(event,
+ InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
/**
@@ -945,7 +946,8 @@ public class Instrumentation {
if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
event.setSource(InputDevice.SOURCE_TRACKBALL);
}
- InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
+ InputManager.getInstance().injectInputEvent(event,
+ InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
/**
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index c2abce5..47e0d1e 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.KeyboardLayout;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -34,4 +35,11 @@ interface IInputManager {
// Injects an input event into the system. To inject into windows owned by other
// applications, the caller must have the INJECT_EVENTS permission.
boolean injectInputEvent(in InputEvent ev, int mode);
+
+ // Keyboard layouts configuration.
+ KeyboardLayout[] getKeyboardLayouts();
+ KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
+ String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor);
+ void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
+ String keyboardLayoutDescriptor);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 5ead1f4..3b3c237 100755
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,37 +16,18 @@
package android.hardware.input;
-import com.android.internal.util.XmlUtils;
-
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
+import android.util.SparseArray;
import android.view.InputDevice;
import android.view.InputEvent;
-import android.view.KeyCharacterMap;
-import android.view.KeyCharacterMap.UnavailableException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
/**
* Provides information about input devices and available key layouts.
@@ -60,13 +41,10 @@ import java.util.List;
public final class InputManager {
private static final String TAG = "InputManager";
- private static final IInputManager sIm;
-
- private final Context mContext;
+ private static InputManager sInstance;
- // Used to simulate a persistent data store.
- // TODO: Replace with the real thing.
- private static final HashMap<String, String> mFakeRegistry = new HashMap<String, String>();
+ private final IInputManager mIm;
+ private final SparseArray<InputDevice> mInputDevices = new SparseArray<InputDevice>();
/**
* Broadcast Action: Query available keyboard layouts.
@@ -169,14 +147,25 @@ public final class InputManager {
*/
public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h
- static {
- IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
- sIm = IInputManager.Stub.asInterface(b);
+ private InputManager(IInputManager im) {
+ mIm = im;
}
- /** @hide */
- public InputManager(Context context) {
- mContext = context;
+ /**
+ * Gets an instance of the input manager.
+ *
+ * @return The input manager instance.
+ *
+ * @hide
+ */
+ public static InputManager getInstance() {
+ synchronized (InputManager.class) {
+ if (sInstance == null) {
+ IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
+ sInstance = new InputManager(IInputManager.Stub.asInterface(b));
+ }
+ return sInstance;
+ }
}
/**
@@ -188,18 +177,16 @@ public final class InputManager {
* </p>
*
* @return A list of all supported keyboard layouts.
+ *
* @hide
*/
- public List<KeyboardLayout> getKeyboardLayouts() {
- ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
-
- final PackageManager pm = mContext.getPackageManager();
- Intent intent = new Intent(ACTION_QUERY_KEYBOARD_LAYOUTS);
- for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
- PackageManager.GET_META_DATA)) {
- loadKeyboardLayouts(pm, resolveInfo.activityInfo, list, null);
+ public KeyboardLayout[] getKeyboardLayouts() {
+ try {
+ return mIm.getKeyboardLayouts();
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
+ return new KeyboardLayout[0];
}
- return list;
}
/**
@@ -216,20 +203,10 @@ public final class InputManager {
throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
}
- KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(keyboardLayoutDescriptor);
- if (d == null) {
- return null;
- }
-
- final PackageManager pm = mContext.getPackageManager();
try {
- ActivityInfo receiver = pm.getReceiverInfo(
- new ComponentName(d.packageName, d.receiverName),
- PackageManager.GET_META_DATA);
- return loadKeyboardLayouts(pm, receiver, null, d.keyboardLayoutName);
- } catch (NameNotFoundException ex) {
- Log.w(TAG, "Could not load keyboard layout '" + d.keyboardLayoutName
- + "' from receiver " + d.packageName + "/" + d.receiverName, ex);
+ return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not get keyboard layout information.", ex);
return null;
}
}
@@ -243,12 +220,17 @@ public final class InputManager {
*
* @hide
*/
- public String getInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor) {
+ public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
- return mFakeRegistry.get(inputDeviceDescriptor);
+ try {
+ return mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not get keyboard layout for input device.", ex);
+ return null;
+ }
}
/**
@@ -264,92 +246,17 @@ public final class InputManager {
*
* @hide
*/
- public void setInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor,
+ public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
String keyboardLayoutDescriptor) {
if (inputDeviceDescriptor == null) {
throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
}
- mFakeRegistry.put(inputDeviceDescriptor, keyboardLayoutDescriptor);
- }
-
- private KeyboardLayout loadKeyboardLayouts(
- PackageManager pm, ActivityInfo receiver,
- List<KeyboardLayout> list, String keyboardName) {
- Bundle metaData = receiver.metaData;
- if (metaData == null) {
- return null;
- }
-
- int configResId = metaData.getInt(META_DATA_KEYBOARD_LAYOUTS);
- if (configResId == 0) {
- Log.w(TAG, "Missing meta-data '" + META_DATA_KEYBOARD_LAYOUTS + "' on receiver "
- + receiver.packageName + "/" + receiver.name);
- return null;
- }
-
try {
- Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
- XmlResourceParser parser = resources.getXml(configResId);
- try {
- XmlUtils.beginDocument(parser, "keyboard-layouts");
-
- for (;;) {
- XmlUtils.nextElement(parser);
- String element = parser.getName();
- if (element == null) {
- break;
- }
- if (element.equals("keyboard-layout")) {
- TypedArray a = resources.obtainAttributes(
- parser, com.android.internal.R.styleable.KeyboardLayout);
- try {
- String name = a.getString(
- com.android.internal.R.styleable.KeyboardLayout_name);
- String label = a.getString(
- com.android.internal.R.styleable.KeyboardLayout_label);
- int kcmResId = a.getResourceId(
- com.android.internal.R.styleable.KeyboardLayout_kcm, 0);
- if (name == null || label == null || kcmResId == 0) {
- Log.w(TAG, "Missing required 'name', 'label' or 'kcm' "
- + "attributes in keyboard layout "
- + "resource from receiver "
- + receiver.packageName + "/" + receiver.name);
- } else {
- String descriptor = makeKeyboardLayoutDescriptor(
- receiver.packageName, receiver.name, name);
- KeyboardLayout c = new KeyboardLayout(
- descriptor, label, kcmResId);
- if (keyboardName != null && name.equals(keyboardName)) {
- return c;
- }
- if (list != null) {
- list.add(c);
- }
- }
- } finally {
- a.recycle();
- }
- } else {
- Log.w(TAG, "Skipping unrecognized element '" + element
- + "' in keyboard layout resource from receiver "
- + receiver.packageName + "/" + receiver.name);
- }
- }
- } finally {
- parser.close();
- }
- } catch (Exception ex) {
- Log.w(TAG, "Could not load keyboard layout resource from receiver "
- + receiver.packageName + "/" + receiver.name, ex);
- return null;
- }
- if (keyboardName != null) {
- Log.w(TAG, "Could not load keyboard layout '" + keyboardName
- + "' from receiver " + receiver.packageName + "/" + receiver.name
- + " because it was not declared in the keyboard layout resource.");
+ mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Could not set keyboard layout for input device.", ex);
}
- return null;
}
/**
@@ -359,15 +266,16 @@ public final class InputManager {
* speed set by {@link #tryPointerSpeed}.
* </p>
*
+ * @param context The application context.
* @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
* {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
*
* @hide
*/
- public int getPointerSpeed() {
+ public int getPointerSpeed(Context context) {
int speed = DEFAULT_POINTER_SPEED;
try {
- speed = Settings.System.getInt(mContext.getContentResolver(),
+ speed = Settings.System.getInt(context.getContentResolver(),
Settings.System.POINTER_SPEED);
} catch (SettingNotFoundException snfe) {
}
@@ -380,17 +288,18 @@ public final class InputManager {
* Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
* </p>
*
+ * @param context The application context.
* @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
* {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
*
* @hide
*/
- public void setPointerSpeed(int speed) {
+ public void setPointerSpeed(Context context, int speed) {
if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
throw new IllegalArgumentException("speed out of range");
}
- Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.putInt(context.getContentResolver(),
Settings.System.POINTER_SPEED, speed);
}
@@ -411,7 +320,7 @@ public final class InputManager {
}
try {
- sIm.tryPointerSpeed(speed);
+ mIm.tryPointerSpeed(speed);
} catch (RemoteException ex) {
Log.w(TAG, "Could not set temporary pointer speed.", ex);
}
@@ -424,12 +333,27 @@ public final class InputManager {
*
* @hide
*/
- public static InputDevice getInputDevice(int id) {
+ public InputDevice getInputDevice(int id) {
+ synchronized (mInputDevices) {
+ InputDevice inputDevice = mInputDevices.get(id);
+ if (inputDevice != null) {
+ return inputDevice;
+ }
+ }
+ final InputDevice newInputDevice;
try {
- return sIm.getInputDevice(id);
+ newInputDevice = mIm.getInputDevice(id);
} catch (RemoteException ex) {
throw new RuntimeException("Could not get input device information.", ex);
}
+ synchronized (mInputDevices) {
+ InputDevice inputDevice = mInputDevices.get(id);
+ if (inputDevice != null) {
+ return inputDevice;
+ }
+ mInputDevices.put(id, newInputDevice);
+ return newInputDevice;
+ }
}
/**
@@ -438,9 +362,9 @@ public final class InputManager {
*
* @hide
*/
- public static int[] getInputDeviceIds() {
+ public int[] getInputDeviceIds() {
try {
- return sIm.getInputDeviceIds();
+ return mIm.getInputDeviceIds();
} catch (RemoteException ex) {
throw new RuntimeException("Could not get input device ids.", ex);
}
@@ -458,10 +382,10 @@ public final class InputManager {
*
* @hide
*/
- public static boolean[] deviceHasKeys(int[] keyCodes) {
+ public boolean[] deviceHasKeys(int[] keyCodes) {
boolean[] ret = new boolean[keyCodes.length];
try {
- sIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret);
+ mIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret);
} catch (RemoteException e) {
// no fallback; just return the empty array
}
@@ -489,7 +413,7 @@ public final class InputManager {
*
* @hide
*/
- public static boolean injectInputEvent(InputEvent event, int mode) {
+ public boolean injectInputEvent(InputEvent event, int mode) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
@@ -500,152 +424,9 @@ public final class InputManager {
}
try {
- return sIm.injectInputEvent(event, mode);
+ return mIm.injectInputEvent(event, mode);
} catch (RemoteException ex) {
return false;
}
}
-
- private static String makeKeyboardLayoutDescriptor(String packageName,
- String receiverName, String keyboardName) {
- return packageName + "/" + receiverName + "/" + keyboardName;
- }
-
- private static KeyboardLayoutDescriptor parseKeyboardLayoutDescriptor(String descriptor) {
- int pos = descriptor.indexOf('/');
- if (pos < 0 || pos + 1 == descriptor.length()) {
- return null;
- }
- int pos2 = descriptor.indexOf('/', pos + 1);
- if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
- return null;
- }
-
- KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
- result.packageName = descriptor.substring(0, pos);
- result.receiverName = descriptor.substring(pos + 1, pos2);
- result.keyboardLayoutName = descriptor.substring(pos2 + 1);
- return result;
- }
-
- /**
- * Describes a keyboard layout.
- *
- * @hide
- */
- public static final class KeyboardLayout implements Parcelable,
- Comparable<KeyboardLayout> {
- private final String mDescriptor;
- private final String mLabel;
- private final int mKeyCharacterMapResId;
-
- private KeyCharacterMap mKeyCharacterMap;
-
- public static final Parcelable.Creator<KeyboardLayout> CREATOR =
- new Parcelable.Creator<KeyboardLayout>() {
- public KeyboardLayout createFromParcel(Parcel source) {
- return new KeyboardLayout(source);
- }
- public KeyboardLayout[] newArray(int size) {
- return new KeyboardLayout[size];
- }
- };
-
- private KeyboardLayout(String descriptor,
- String label, int keyCharacterMapResId) {
- mDescriptor = descriptor;
- mLabel = label;
- mKeyCharacterMapResId = keyCharacterMapResId;
- }
-
- private KeyboardLayout(Parcel source) {
- mDescriptor = source.readString();
- mLabel = source.readString();
- mKeyCharacterMapResId = source.readInt();
- }
-
- /**
- * Gets the keyboard layout descriptor, which can be used to retrieve
- * the keyboard layout again later using
- * {@link InputManager#getKeyboardLayout(String)}.
- *
- * @return The keyboard layout descriptor.
- */
- public String getDescriptor() {
- return mDescriptor;
- }
-
- /**
- * Gets the keyboard layout descriptive label to show in the user interface.
- * @return The keyboard layout descriptive label.
- */
- public String getLabel() {
- return mLabel;
- }
-
- /**
- * Loads the key character map associated with the keyboard layout.
- *
- * @param pm The package manager.
- * @return The key character map, or null if it could not be loaded for any reason.
- */
- public KeyCharacterMap loadKeyCharacterMap(PackageManager pm) {
- if (pm == null) {
- throw new IllegalArgumentException("pm must not be null");
- }
-
- if (mKeyCharacterMap == null) {
- KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(mDescriptor);
- if (d == null) {
- Log.e(TAG, "Could not load key character map '" + mDescriptor
- + "' because the descriptor could not be parsed.");
- return null;
- }
-
- CharSequence cs = pm.getText(d.packageName, mKeyCharacterMapResId, null);
- if (cs == null) {
- Log.e(TAG, "Could not load key character map '" + mDescriptor
- + "' because its associated resource could not be loaded.");
- return null;
- }
-
- try {
- mKeyCharacterMap = KeyCharacterMap.load(cs);
- } catch (UnavailableException ex) {
- Log.e(TAG, "Could not load key character map '" + mDescriptor
- + "' due to an error while parsing.", ex);
- return null;
- }
- }
- return mKeyCharacterMap;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mDescriptor);
- dest.writeString(mLabel);
- dest.writeInt(mKeyCharacterMapResId);
- }
-
- @Override
- public int compareTo(KeyboardLayout another) {
- return mLabel.compareToIgnoreCase(another.mLabel);
- }
-
- @Override
- public String toString() {
- return mLabel;
- }
- }
-
- private static final class KeyboardLayoutDescriptor {
- public String packageName;
- public String receiverName;
- public String keyboardLayoutName;
- }
}
diff --git a/core/java/android/hardware/input/KeyboardLayout.aidl b/core/java/android/hardware/input/KeyboardLayout.aidl
new file mode 100644
index 0000000..226e384
--- /dev/null
+++ b/core/java/android/hardware/input/KeyboardLayout.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2012 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 KeyboardLayout;
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
new file mode 100644
index 0000000..e75a6dc
--- /dev/null
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 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;
+
+/**
+ * Describes a keyboard layout.
+ *
+ * @hide
+ */
+public final class KeyboardLayout implements Parcelable,
+ Comparable<KeyboardLayout> {
+ private final String mDescriptor;
+ private final String mLabel;
+
+ public static final Parcelable.Creator<KeyboardLayout> CREATOR =
+ new Parcelable.Creator<KeyboardLayout>() {
+ public KeyboardLayout createFromParcel(Parcel source) {
+ return new KeyboardLayout(source);
+ }
+ public KeyboardLayout[] newArray(int size) {
+ return new KeyboardLayout[size];
+ }
+ };
+
+ public KeyboardLayout(String descriptor, String label) {
+ mDescriptor = descriptor;
+ mLabel = label;
+ }
+
+ private KeyboardLayout(Parcel source) {
+ mDescriptor = source.readString();
+ mLabel = source.readString();
+ }
+
+ /**
+ * Gets the keyboard layout descriptor, which can be used to retrieve
+ * the keyboard layout again later using
+ * {@link InputManager#getKeyboardLayout(String)}.
+ *
+ * @return The keyboard layout descriptor.
+ */
+ public String getDescriptor() {
+ return mDescriptor;
+ }
+
+ /**
+ * Gets the keyboard layout descriptive label to show in the user interface.
+ * @return The keyboard layout descriptive label.
+ */
+ public String getLabel() {
+ return mLabel;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mDescriptor);
+ dest.writeString(mLabel);
+ }
+
+ @Override
+ public int compareTo(KeyboardLayout another) {
+ return mLabel.compareToIgnoreCase(another.mLabel);
+ }
+
+ @Override
+ public String toString() {
+ return mLabel;
+ }
+} \ No newline at end of file
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 6f8d09b..75b2c746 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -39,13 +39,12 @@ import java.util.List;
* </p>
*/
public final class InputDevice implements Parcelable {
- private int mId;
- private String mName;
- private String mDescriptor;
- private int mSources;
- private int mKeyboardType;
- private String mKeyCharacterMapFile;
-
+ private final int mId;
+ private final String mName;
+ private final String mDescriptor;
+ private final int mSources;
+ private final int mKeyboardType;
+ private final KeyCharacterMap mKeyCharacterMap;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
/**
@@ -292,8 +291,43 @@ public final class InputDevice implements Parcelable {
*/
public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
+ public static final Parcelable.Creator<InputDevice> CREATOR =
+ new Parcelable.Creator<InputDevice>() {
+ public InputDevice createFromParcel(Parcel in) {
+ return new InputDevice(in);
+ }
+ public InputDevice[] newArray(int size) {
+ return new InputDevice[size];
+ }
+ };
+
// Called by native code.
- private InputDevice() {
+ private InputDevice(int id, String name, String descriptor, int sources,
+ int keyboardType, KeyCharacterMap keyCharacterMap) {
+ mId = id;
+ mName = name;
+ mDescriptor = descriptor;
+ mSources = sources;
+ mKeyboardType = keyboardType;
+ mKeyCharacterMap = keyCharacterMap;
+ }
+
+ private InputDevice(Parcel in) {
+ mId = in.readInt();
+ mName = in.readString();
+ mDescriptor = in.readString();
+ mSources = in.readInt();
+ mKeyboardType = in.readInt();
+ mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
+
+ for (;;) {
+ int axis = in.readInt();
+ if (axis < 0) {
+ break;
+ }
+ addMotionRange(axis, in.readInt(),
+ in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
+ }
}
/**
@@ -302,7 +336,7 @@ public final class InputDevice implements Parcelable {
* @return The input device or null if not found.
*/
public static InputDevice getDevice(int id) {
- return InputManager.getInputDevice(id);
+ return InputManager.getInstance().getInputDevice(id);
}
/**
@@ -310,7 +344,7 @@ public final class InputDevice implements Parcelable {
* @return The input device ids.
*/
public static int[] getDeviceIds() {
- return InputManager.getInputDeviceIds();
+ return InputManager.getInstance().getInputDeviceIds();
}
/**
@@ -356,6 +390,22 @@ public final class InputDevice implements Parcelable {
}
/**
+ * Returns true if the device is a virtual input device rather than a real one,
+ * such as the virtual keyboard (see {@link KeyCharacterMap#VIRTUAL_KEYBOARD}).
+ * <p>
+ * Virtual input devices are provided to implement system-level functionality
+ * and should not be seen or configured by users.
+ * </p>
+ *
+ * @return True if the device is virtual.
+ *
+ * @see KeyCharacterMap#VIRTUAL_KEYBOARD
+ */
+ public boolean isVirtual() {
+ return mId < 0;
+ }
+
+ /**
* Gets the name of this input device.
* @return The input device name.
*/
@@ -384,11 +434,7 @@ public final class InputDevice implements Parcelable {
* @return The key character map.
*/
public KeyCharacterMap getKeyCharacterMap() {
- return KeyCharacterMap.load(mId);
- }
-
- String getKeyCharacterMapFile() {
- return mKeyCharacterMapFile;
+ return mKeyCharacterMap;
}
/**
@@ -453,6 +499,7 @@ public final class InputDevice implements Parcelable {
return mMotionRanges;
}
+ // Called from native code.
private void addMotionRange(int axis, int source,
float min, float max, float flat, float fuzz) {
mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
@@ -545,37 +592,6 @@ public final class InputDevice implements Parcelable {
}
}
- public static final Parcelable.Creator<InputDevice> CREATOR
- = new Parcelable.Creator<InputDevice>() {
- public InputDevice createFromParcel(Parcel in) {
- InputDevice result = new InputDevice();
- result.readFromParcel(in);
- return result;
- }
-
- public InputDevice[] newArray(int size) {
- return new InputDevice[size];
- }
- };
-
- private void readFromParcel(Parcel in) {
- mId = in.readInt();
- mName = in.readString();
- mDescriptor = in.readString();
- mSources = in.readInt();
- mKeyboardType = in.readInt();
- mKeyCharacterMapFile = in.readString();
-
- for (;;) {
- int axis = in.readInt();
- if (axis < 0) {
- break;
- }
- addMotionRange(axis, in.readInt(),
- in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
- }
- }
-
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
@@ -583,7 +599,7 @@ public final class InputDevice implements Parcelable {
out.writeString(mDescriptor);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
- out.writeString(mKeyCharacterMapFile);
+ mKeyCharacterMap.writeToParcel(out, flags);
final int numRanges = mMotionRanges.size();
for (int i = 0; i < numRanges; i++) {
@@ -623,8 +639,6 @@ public final class InputDevice implements Parcelable {
}
description.append("\n");
- description.append(" Key Character Map: ").append(mKeyCharacterMapFile).append("\n");
-
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index b03f086..3d165ea 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,18 +16,21 @@
package android.view;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.text.method.MetaKeyKeyListener;
import android.util.AndroidRuntimeException;
import android.util.SparseIntArray;
import android.hardware.input.InputManager;
import android.util.SparseArray;
+import android.view.InputDevice.MotionRange;
import java.lang.Character;
/**
* Describes the keys provided by a keyboard device and their associated labels.
*/
-public class KeyCharacterMap {
+public class KeyCharacterMap implements Parcelable {
/**
* The id of the device's primary built in keyboard is always 0.
*
@@ -134,12 +137,20 @@ public class KeyCharacterMap {
*/
public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1;
- private static SparseArray<KeyCharacterMap> sInstances = new SparseArray<KeyCharacterMap>();
+ public static final Parcelable.Creator<KeyCharacterMap> CREATOR =
+ new Parcelable.Creator<KeyCharacterMap>() {
+ public KeyCharacterMap createFromParcel(Parcel in) {
+ return new KeyCharacterMap(in);
+ }
+ public KeyCharacterMap[] newArray(int size) {
+ return new KeyCharacterMap[size];
+ }
+ };
- private final int mDeviceId;
private int mPtr;
- private static native int nativeLoad(String file);
+ private static native int nativeReadFromParcel(Parcel in);
+ private static native void nativeWriteToParcel(int ptr, Parcel out);
private static native void nativeDispose(int ptr);
private static native char nativeGetCharacter(int ptr, int keyCode, int metaState);
@@ -149,10 +160,20 @@ public class KeyCharacterMap {
private static native char nativeGetMatch(int ptr, int keyCode, char[] chars, int metaState);
private static native char nativeGetDisplayLabel(int ptr, int keyCode);
private static native int nativeGetKeyboardType(int ptr);
- private static native KeyEvent[] nativeGetEvents(int ptr, int deviceId, char[] chars);
+ private static native KeyEvent[] nativeGetEvents(int ptr, char[] chars);
+
+ private KeyCharacterMap(Parcel in) {
+ if (in == null) {
+ throw new IllegalArgumentException("parcel must not be null");
+ }
+ mPtr = nativeReadFromParcel(in);
+ if (mPtr == 0) {
+ throw new RuntimeException("Could not read KeyCharacterMap from parcel.");
+ }
+ }
- private KeyCharacterMap(int deviceId, int ptr) {
- mDeviceId = deviceId;
+ // Called from native
+ private KeyCharacterMap(int ptr) {
mPtr = ptr;
}
@@ -174,33 +195,16 @@ public class KeyCharacterMap {
* is missing from the system.
*/
public static KeyCharacterMap load(int deviceId) {
- synchronized (sInstances) {
- KeyCharacterMap map = sInstances.get(deviceId);
- if (map == null) {
- String kcm = null;
- if (deviceId != VIRTUAL_KEYBOARD) {
- InputDevice device = InputDevice.getDevice(deviceId);
- if (device != null) {
- kcm = device.getKeyCharacterMapFile();
- }
- }
- if (kcm == null || kcm.length() == 0) {
- kcm = "/system/usr/keychars/Virtual.kcm";
- }
- int ptr = nativeLoad(kcm); // might throw
- map = new KeyCharacterMap(deviceId, ptr);
- sInstances.put(deviceId, map);
+ final InputManager im = InputManager.getInstance();
+ InputDevice inputDevice = im.getInputDevice(deviceId);
+ if (inputDevice == null) {
+ inputDevice = im.getInputDevice(VIRTUAL_KEYBOARD);
+ if (inputDevice == null) {
+ throw new UnavailableException(
+ "Could not load key character map for device " + deviceId);
}
- return map;
}
- }
-
- /**
- * TODO implement this
- * @hide
- */
- public static KeyCharacterMap load(CharSequence contents) {
- return null;
+ return inputDevice.getKeyCharacterMap();
}
/**
@@ -437,7 +441,7 @@ public class KeyCharacterMap {
if (chars == null) {
throw new IllegalArgumentException("chars must not be null.");
}
- return nativeGetEvents(mPtr, mDeviceId, chars);
+ return nativeGetEvents(mPtr, chars);
}
/**
@@ -527,7 +531,7 @@ public class KeyCharacterMap {
* @return True if at least one attached keyboard supports the specified key code.
*/
public static boolean deviceHasKey(int keyCode) {
- return InputManager.deviceHasKeys(new int[] { keyCode })[0];
+ return InputManager.getInstance().deviceHasKeys(new int[] { keyCode })[0];
}
/**
@@ -541,7 +545,20 @@ public class KeyCharacterMap {
* at the same index in the key codes array.
*/
public static boolean[] deviceHasKeys(int[] keyCodes) {
- return InputManager.deviceHasKeys(keyCodes);
+ return InputManager.getInstance().deviceHasKeys(keyCodes);
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ if (out == null) {
+ throw new IllegalArgumentException("parcel must not be null");
+ }
+ nativeWriteToParcel(mPtr, out);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
}
/**