Loading api/current.txt +12 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,7 @@ package android { field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131 field public static final int itemPadding = 16843565; // 0x101032d field public static final int itemTextAppearance = 16843052; // 0x101012c field public static final int kcm = 16843694; // 0x10103ae field public static final int keepScreenOn = 16843286; // 0x1010216 field public static final int key = 16843240; // 0x10101e8 field public static final int keyBackground = 16843315; // 0x1010233 Loading Loading @@ -5232,6 +5233,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final java.lang.String LOCATION_SERVICE = "location"; Loading Loading @@ -9817,6 +9819,15 @@ package android.hardware { } package android.hardware.input { public final class InputManager { field public static final java.lang.String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS"; field public static final java.lang.String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; } } package android.hardware.usb { public class UsbAccessory implements android.os.Parcelable { Loading Loading @@ -22247,6 +22258,7 @@ package android.view { public final class InputDevice implements android.os.Parcelable { method public int describeContents(); method public java.lang.String getDescriptor(); method public static android.view.InputDevice getDevice(int); method public static int[] getDeviceIds(); method public int getId(); core/java/android/app/ContextImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.graphics.drawable.Drawable; import android.hardware.ISerialManager; import android.hardware.SensorManager; import android.hardware.SerialManager; import android.hardware.input.InputManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; import android.location.CountryDetector; Loading Loading @@ -323,6 +324,11 @@ class ContextImpl extends Context { return createDropBoxManager(); }}); registerService(INPUT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new InputManager(ctx); }}); registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return InputMethodManager.getInstance(ctx); Loading core/java/android/content/Context.java +9 −0 Original line number Diff line number Diff line Loading @@ -1918,6 +1918,15 @@ public abstract class Context { */ public static final String SERIAL_SERVICE = "serial"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.hardware.input.InputManager} for interacting with input devices. * * @see #getSystemService * @see android.hardware.input.InputManager */ public static final String INPUT_SERVICE = "input"; /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. Loading core/java/android/hardware/input/InputManager.java 0 → 100755 +441 −0 Original line number Diff line number Diff line /* * 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 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.Parcel; import android.os.Parcelable; import android.util.Log; 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. * <p> * Get an instance of this class by calling * {@link android.content.Context#getSystemService(java.lang.String) * Context.getSystemService()} with the argument * {@link android.content.Context#INPUT_SERVICE}. * </p> */ public final class InputManager { private static final String TAG = "InputManager"; private final Context mContext; // Used to simulate a persistent data store. // TODO: Replace with the real thing. private static final HashMap<String, String> mFakeRegistry = new HashMap<String, String>(); /** * Broadcast Action: Query available keyboard layouts. * <p> * The input manager service locates available keyboard layouts * by querying broadcast receivers that are registered for this action. * An application can offer additional keyboard layouts to the user * by declaring a suitable broadcast receiver in its manifest. * </p><p> * Here is an example broadcast receiver declaration that an application * might include in its AndroidManifest.xml to advertise keyboard layouts. * The meta-data specifies a resource that contains a description of each keyboard * layout that is provided by the application. * <pre><code> * <receiver android:name=".InputDeviceReceiver"> * <intent-filter> * <action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" /> * </intent-filter> * <meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS" * android:resource="@xml/keyboard_layouts" /> * </receiver> * </code></pre> * </p><p> * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to * an XML resource whose root element is <code><keyboard-layouts></code> that * contains zero or more <code><keyboard-layout></code> elements. * Each <code><keyboard-layout></code> element specifies the name, label, and location * of a key character map for a particular keyboard layout. * <pre></code> * <?xml version="1.0" encoding="utf-8"?> * <keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android"> * <keyboard-layout android:name="keyboard_layout_english_us" * android:label="@string/keyboard_layout_english_us_label" * android:kcm="@raw/keyboard_layout_english_us" /> * </keyboard-layouts> * </p><p> * The <code>android:name</code> attribute specifies an identifier by which * the keyboard layout will be known in the package. * The <code>android:label</code> attributes specifies a human-readable descriptive * label to describe the keyboard layout in the user interface, such as "English (US)". * The <code>android:kcm</code> attribute refers to a * <a href="http://source.android.com/tech/input/key-character-map-files.html"> * key character map</a> resource that defines the keyboard layout. * </p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS"; /** * Metadata Key: Keyboard layout metadata associated with * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}. * <p> * Specifies the resource id of a XML resource that describes the keyboard * layouts that are provided by the application. * </p> */ public static final String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; /** @hide */ public InputManager(Context context) { mContext = context; } /** * Gets information about all supported keyboard layouts. * <p> * The input manager consults the built-in keyboard layouts as well * as all keyboard layouts advertised by applications using a * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver. * </p> * * @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); } return list; } /** * Gets the keyboard layout with the specified descriptor. * * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by * {@link KeyboardLayout#getDescriptor()}. * @return The keyboard layout, or null if it could not be loaded. * * @hide */ public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { if (keyboardLayoutDescriptor == null) { 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 null; } } /** * Gets the keyboard layout descriptor for the specified input device. * * @param inputDeviceDescriptor The input device descriptor. * @return The keyboard layout descriptor, or null if unknown or if the default * keyboard layout will be used. * * @hide */ public String getInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor) { if (inputDeviceDescriptor == null) { throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); } return mFakeRegistry.get(inputDeviceDescriptor); } /** * Sets 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. * </p> * * @param inputDeviceDescriptor The input device descriptor. * @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove * the mapping so that the default keyboard layout will be used for the input device. * * @hide */ public void setInputDeviceKeyboardLayoutDescriptor(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."); } return null; } 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; } } core/java/android/view/InputDevice.java +30 −4 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import java.util.List; /** * Describes the capabilities of a particular input device. * <p> * Each input device may support multiple classes of input. For example, a multifunction * Each input device may support multiple classes of input. For example, a multi-function * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse * or other pointing device. * </p><p> Loading Loading @@ -119,6 +119,10 @@ public final class InputDevice implements Parcelable { /** * The input source is a keyboard. * * This source indicates pretty much anything that has buttons. Use * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys * and can be used to enter text. * * @see #SOURCE_CLASS_BUTTON */ public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON; Loading Loading @@ -322,12 +326,34 @@ public final class InputDevice implements Parcelable { /** * Gets the input device id. * <p> * Each input device receives a unique id when it is first configured * by the system. The input device id may change when the system is restarted or if the * input device is disconnected, reconnected or reconfigured at any time. * If you require a stable identifier for a device that persists across * boots and reconfigurations, use {@link #getDescriptor()}. * </p> * * @return The input device id. */ public int getId() { return mId; } /** * Gets the input device descriptor, which is a stable identifier for an input device. * <p> * An input device descriptor uniquely identifies an input device. Its value * is intended to be persistent across system restarts, and should not change even * if the input device is disconnected, reconnected or reconfigured at any time. * </p> * * @return The input device descriptor. */ public String getDescriptor() { return "PLACEHOLDER"; // TODO: implement for real } /** * Gets the name of this input device. * @return The input device name. Loading Loading
api/current.txt +12 −0 Original line number Diff line number Diff line Loading @@ -570,6 +570,7 @@ package android { field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131 field public static final int itemPadding = 16843565; // 0x101032d field public static final int itemTextAppearance = 16843052; // 0x101012c field public static final int kcm = 16843694; // 0x10103ae field public static final int keepScreenOn = 16843286; // 0x1010216 field public static final int key = 16843240; // 0x10101e8 field public static final int keyBackground = 16843315; // 0x1010233 Loading Loading @@ -5232,6 +5233,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater"; field public static final java.lang.String LOCATION_SERVICE = "location"; Loading Loading @@ -9817,6 +9819,15 @@ package android.hardware { } package android.hardware.input { public final class InputManager { field public static final java.lang.String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS"; field public static final java.lang.String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; } } package android.hardware.usb { public class UsbAccessory implements android.os.Parcelable { Loading Loading @@ -22247,6 +22258,7 @@ package android.view { public final class InputDevice implements android.os.Parcelable { method public int describeContents(); method public java.lang.String getDescriptor(); method public static android.view.InputDevice getDevice(int); method public static int[] getDeviceIds(); method public int getId();
core/java/android/app/ContextImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.graphics.drawable.Drawable; import android.hardware.ISerialManager; import android.hardware.SensorManager; import android.hardware.SerialManager; import android.hardware.input.InputManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; import android.location.CountryDetector; Loading Loading @@ -323,6 +324,11 @@ class ContextImpl extends Context { return createDropBoxManager(); }}); registerService(INPUT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new InputManager(ctx); }}); registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return InputMethodManager.getInstance(ctx); Loading
core/java/android/content/Context.java +9 −0 Original line number Diff line number Diff line Loading @@ -1918,6 +1918,15 @@ public abstract class Context { */ public static final String SERIAL_SERVICE = "serial"; /** * Use with {@link #getSystemService} to retrieve a * {@link android.hardware.input.InputManager} for interacting with input devices. * * @see #getSystemService * @see android.hardware.input.InputManager */ public static final String INPUT_SERVICE = "input"; /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. Loading
core/java/android/hardware/input/InputManager.java 0 → 100755 +441 −0 Original line number Diff line number Diff line /* * 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 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.Parcel; import android.os.Parcelable; import android.util.Log; 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. * <p> * Get an instance of this class by calling * {@link android.content.Context#getSystemService(java.lang.String) * Context.getSystemService()} with the argument * {@link android.content.Context#INPUT_SERVICE}. * </p> */ public final class InputManager { private static final String TAG = "InputManager"; private final Context mContext; // Used to simulate a persistent data store. // TODO: Replace with the real thing. private static final HashMap<String, String> mFakeRegistry = new HashMap<String, String>(); /** * Broadcast Action: Query available keyboard layouts. * <p> * The input manager service locates available keyboard layouts * by querying broadcast receivers that are registered for this action. * An application can offer additional keyboard layouts to the user * by declaring a suitable broadcast receiver in its manifest. * </p><p> * Here is an example broadcast receiver declaration that an application * might include in its AndroidManifest.xml to advertise keyboard layouts. * The meta-data specifies a resource that contains a description of each keyboard * layout that is provided by the application. * <pre><code> * <receiver android:name=".InputDeviceReceiver"> * <intent-filter> * <action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" /> * </intent-filter> * <meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS" * android:resource="@xml/keyboard_layouts" /> * </receiver> * </code></pre> * </p><p> * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to * an XML resource whose root element is <code><keyboard-layouts></code> that * contains zero or more <code><keyboard-layout></code> elements. * Each <code><keyboard-layout></code> element specifies the name, label, and location * of a key character map for a particular keyboard layout. * <pre></code> * <?xml version="1.0" encoding="utf-8"?> * <keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android"> * <keyboard-layout android:name="keyboard_layout_english_us" * android:label="@string/keyboard_layout_english_us_label" * android:kcm="@raw/keyboard_layout_english_us" /> * </keyboard-layouts> * </p><p> * The <code>android:name</code> attribute specifies an identifier by which * the keyboard layout will be known in the package. * The <code>android:label</code> attributes specifies a human-readable descriptive * label to describe the keyboard layout in the user interface, such as "English (US)". * The <code>android:kcm</code> attribute refers to a * <a href="http://source.android.com/tech/input/key-character-map-files.html"> * key character map</a> resource that defines the keyboard layout. * </p> */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS"; /** * Metadata Key: Keyboard layout metadata associated with * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}. * <p> * Specifies the resource id of a XML resource that describes the keyboard * layouts that are provided by the application. * </p> */ public static final String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; /** @hide */ public InputManager(Context context) { mContext = context; } /** * Gets information about all supported keyboard layouts. * <p> * The input manager consults the built-in keyboard layouts as well * as all keyboard layouts advertised by applications using a * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver. * </p> * * @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); } return list; } /** * Gets the keyboard layout with the specified descriptor. * * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by * {@link KeyboardLayout#getDescriptor()}. * @return The keyboard layout, or null if it could not be loaded. * * @hide */ public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { if (keyboardLayoutDescriptor == null) { 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 null; } } /** * Gets the keyboard layout descriptor for the specified input device. * * @param inputDeviceDescriptor The input device descriptor. * @return The keyboard layout descriptor, or null if unknown or if the default * keyboard layout will be used. * * @hide */ public String getInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor) { if (inputDeviceDescriptor == null) { throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); } return mFakeRegistry.get(inputDeviceDescriptor); } /** * Sets 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. * </p> * * @param inputDeviceDescriptor The input device descriptor. * @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove * the mapping so that the default keyboard layout will be used for the input device. * * @hide */ public void setInputDeviceKeyboardLayoutDescriptor(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."); } return null; } 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; } }
core/java/android/view/InputDevice.java +30 −4 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import java.util.List; /** * Describes the capabilities of a particular input device. * <p> * Each input device may support multiple classes of input. For example, a multifunction * Each input device may support multiple classes of input. For example, a multi-function * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse * or other pointing device. * </p><p> Loading Loading @@ -119,6 +119,10 @@ public final class InputDevice implements Parcelable { /** * The input source is a keyboard. * * This source indicates pretty much anything that has buttons. Use * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys * and can be used to enter text. * * @see #SOURCE_CLASS_BUTTON */ public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON; Loading Loading @@ -322,12 +326,34 @@ public final class InputDevice implements Parcelable { /** * Gets the input device id. * <p> * Each input device receives a unique id when it is first configured * by the system. The input device id may change when the system is restarted or if the * input device is disconnected, reconnected or reconfigured at any time. * If you require a stable identifier for a device that persists across * boots and reconfigurations, use {@link #getDescriptor()}. * </p> * * @return The input device id. */ public int getId() { return mId; } /** * Gets the input device descriptor, which is a stable identifier for an input device. * <p> * An input device descriptor uniquely identifies an input device. Its value * is intended to be persistent across system restarts, and should not change even * if the input device is disconnected, reconnected or reconfigured at any time. * </p> * * @return The input device descriptor. */ public String getDescriptor() { return "PLACEHOLDER"; // TODO: implement for real } /** * Gets the name of this input device. * @return The input device name. Loading