/*
 * Copyright (C) 2007 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.view;

import android.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.method.MetaKeyKeyListener;
import android.util.AndroidRuntimeException;
import android.util.SparseIntArray;

import java.text.Normalizer;

/**
 * Describes the keys provided by a keyboard device and their associated labels.
 */
public class KeyCharacterMap implements Parcelable {
    /**
     * The id of the device's primary built in keyboard is always 0.
     *
     * @deprecated This constant should no longer be used because there is no
     * guarantee that a device has a built-in keyboard that can be used for
     * typing text.  There might not be a built-in keyboard, the built-in keyboard
     * might be a {@link #NUMERIC} or {@link #SPECIAL_FUNCTION} keyboard, or there
     * might be multiple keyboards installed including external keyboards.
     * When interpreting key presses received from the framework, applications should
     * use the device id specified in the {@link KeyEvent} received.
     * When synthesizing key presses for delivery elsewhere or when translating key presses
     * from unknown keyboards, applications should use the special {@link #VIRTUAL_KEYBOARD}
     * device id.
     */
    @Deprecated
    public static final int BUILT_IN_KEYBOARD = 0;

    /**
     * The id of a generic virtual keyboard with a full layout that can be used to
     * synthesize key events.  Typically used with {@link #getEvents}.
     */
    public static final int VIRTUAL_KEYBOARD = -1;

    /**
     * A numeric (12-key) keyboard.
     * <p>
     * A numeric keyboard supports text entry using a multi-tap approach.
     * It may be necessary to tap a key multiple times to generate the desired letter
     * or symbol.
     * </p><p>
     * This type of keyboard is generally designed for thumb typing.
     * </p>
     */
    public static final int NUMERIC = 1;

    /**
     * A keyboard with all the letters, but with more than one letter per key.
     * <p>
     * This type of keyboard is generally designed for thumb typing.
     * </p>
     */
    public static final int PREDICTIVE = 2;

    /**
     * A keyboard with all the letters, and maybe some numbers.
     * <p>
     * An alphabetic keyboard supports text entry directly but may have a condensed
     * layout with a small form factor.  In contrast to a {@link #FULL full keyboard}, some
     * symbols may only be accessible using special on-screen character pickers.
     * In addition, to improve typing speed and accuracy, the framework provides
     * special affordances for alphabetic keyboards such as auto-capitalization
     * and toggled / locked shift and alt keys.
     * </p><p>
     * This type of keyboard is generally designed for thumb typing.
     * </p>
     */
    public static final int ALPHA = 3;

    /**
     * A full PC-style keyboard.
     * <p>
     * A full keyboard behaves like a PC keyboard.  All symbols are accessed directly
     * by pressing keys on the keyboard without on-screen support or affordances such
     * as auto-capitalization.
     * </p><p>
     * This type of keyboard is generally designed for full two hand typing.
     * </p>
     */
    public static final int FULL = 4;

    /**
     * A keyboard that is only used to control special functions rather than for typing.
     * <p>
     * A special function keyboard consists only of non-printing keys such as
     * HOME and POWER that are not actually used for typing.
     * </p>
     */
    public static final int SPECIAL_FUNCTION = 5;

    /**
     * This private-use character is used to trigger Unicode character
     * input by hex digits.
     */
    public static final char HEX_INPUT = '\uEF00';

    /**
     * This private-use character is used to bring up a character picker for
     * miscellaneous symbols.
     */
    public static final char PICKER_DIALOG_INPUT = '\uEF01';

    /**
     * Modifier keys may be chorded with character keys.
     *
     * @see {#link #getModifierBehavior()} for more details.
     */
    public static final int MODIFIER_BEHAVIOR_CHORDED = 0;

    /**
     * Modifier keys may be chorded with character keys or they may toggle
     * into latched or locked states when pressed independently.
     *
     * @see {#link #getModifierBehavior()} for more details.
     */
    public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1;

    /*
     * This bit will be set in the return value of {@link #get(int, int)} if the
     * key is a "dead key."
     */
    public static final int COMBINING_ACCENT = 0x80000000;

    /**
     * Mask the return value from {@link #get(int, int)} with this value to get
     * a printable representation of the accent character of a "dead key."
     */
    public static final int COMBINING_ACCENT_MASK = 0x7FFFFFFF;

    /* Characters used to display placeholders for dead keys. */
    private static final int ACCENT_ACUTE = '\u00B4';
    private static final int ACCENT_BREVE = '\u02D8';
    private static final int ACCENT_CARON = '\u02C7';
    private static final int ACCENT_CEDILLA = '\u00B8';
    private static final int ACCENT_CIRCUMFLEX = '\u02C6';
    private static final int ACCENT_COMMA_ABOVE = '\u1FBD';
    private static final int ACCENT_COMMA_ABOVE_RIGHT = '\u02BC';
    private static final int ACCENT_DOT_ABOVE = '\u02D9';
    private static final int ACCENT_DOT_BELOW = '.'; // approximate
    private static final int ACCENT_DOUBLE_ACUTE = '\u02DD';
    private static final int ACCENT_GRAVE = '\u02CB';
    private static final int ACCENT_HOOK_ABOVE = '\u02C0';
    private static final int ACCENT_HORN = '\''; // approximate
    private static final int ACCENT_MACRON = '\u00AF';
    private static final int ACCENT_MACRON_BELOW = '\u02CD';
    private static final int ACCENT_OGONEK = '\u02DB';
    private static final int ACCENT_REVERSED_COMMA_ABOVE = '\u02BD';
    private static final int ACCENT_RING_ABOVE = '\u02DA';
    private static final int ACCENT_STROKE = '-'; // approximate
    private static final int ACCENT_TILDE = '\u02DC';
    private static final int ACCENT_TURNED_COMMA_ABOVE = '\u02BB';
    private static final int ACCENT_UMLAUT = '\u00A8';
    private static final int ACCENT_VERTICAL_LINE_ABOVE = '\u02C8';
    private static final int ACCENT_VERTICAL_LINE_BELOW = '\u02CC';

    /* Legacy dead key display characters used in previous versions of the API.
     * We still support these characters by mapping them to their non-legacy version. */
    private static final int ACCENT_GRAVE_LEGACY = '`';
    private static final int ACCENT_CIRCUMFLEX_LEGACY = '^';
    private static final int ACCENT_TILDE_LEGACY = '~';

    private static final int CHAR_SPACE = ' ';

    /**
     * Maps Unicode combining diacritical to display-form dead key.
     */
    private static final SparseIntArray sCombiningToAccent = new SparseIntArray();
    private static final SparseIntArray sAccentToCombining = new SparseIntArray();
    static {
        addCombining('\u0300', ACCENT_GRAVE);
        addCombining('\u0301', ACCENT_ACUTE);
        addCombining('\u0302', ACCENT_CIRCUMFLEX);
        addCombining('\u0303', ACCENT_TILDE);
        addCombining('\u0304', ACCENT_MACRON);
        addCombining('\u0306', ACCENT_BREVE);
        addCombining('\u0307', ACCENT_DOT_ABOVE);
        addCombining('\u0308', ACCENT_UMLAUT);
        addCombining('\u0309', ACCENT_HOOK_ABOVE);
        addCombining('\u030A', ACCENT_RING_ABOVE);
        addCombining('\u030B', ACCENT_DOUBLE_ACUTE);
        addCombining('\u030C', ACCENT_CARON);
        addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE);
        //addCombining('\u030E', ACCENT_DOUBLE_VERTICAL_LINE_ABOVE);
        //addCombining('\u030F', ACCENT_DOUBLE_GRAVE);
        //addCombining('\u0310', ACCENT_CANDRABINDU);
        //addCombining('\u0311', ACCENT_INVERTED_BREVE);
        addCombining('\u0312', ACCENT_TURNED_COMMA_ABOVE);
        addCombining('\u0313', ACCENT_COMMA_ABOVE);
        addCombining('\u0314', ACCENT_REVERSED_COMMA_ABOVE);
        addCombining('\u0315', ACCENT_COMMA_ABOVE_RIGHT);
        addCombining('\u031B', ACCENT_HORN);
        addCombining('\u0323', ACCENT_DOT_BELOW);
        //addCombining('\u0326', ACCENT_COMMA_BELOW);
        addCombining('\u0327', ACCENT_CEDILLA);
        addCombining('\u0328', ACCENT_OGONEK);
        addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW);
        addCombining('\u0331', ACCENT_MACRON_BELOW);
        addCombining('\u0335', ACCENT_STROKE);
        //addCombining('\u0342', ACCENT_PERISPOMENI);
        //addCombining('\u0344', ACCENT_DIALYTIKA_TONOS);
        //addCombining('\u0345', ACCENT_YPOGEGRAMMENI);

        // One-way mappings to equivalent preferred accents.
        sCombiningToAccent.append('\u0340', ACCENT_GRAVE);
        sCombiningToAccent.append('\u0341', ACCENT_ACUTE);
        sCombiningToAccent.append('\u0343', ACCENT_COMMA_ABOVE);

        // One-way legacy mappings to preserve compatibility with older applications.
        sAccentToCombining.append(ACCENT_GRAVE_LEGACY, '\u0300');
        sAccentToCombining.append(ACCENT_CIRCUMFLEX_LEGACY, '\u0302');
        sAccentToCombining.append(ACCENT_TILDE_LEGACY, '\u0303');
    }

    private static void addCombining(int combining, int accent) {
        sCombiningToAccent.append(combining, accent);
        sAccentToCombining.append(accent, combining);
    }

    /**
     * Maps combinations of (display-form) combining key and second character
     * to combined output character.
     * These mappings are derived from the Unicode NFC tables as needed.
     */
    private static final SparseIntArray sDeadKeyCache = new SparseIntArray();
    private static final StringBuilder sDeadKeyBuilder = new StringBuilder();
    static {
        // Non-standard decompositions.
        // Stroke modifier for Finnish multilingual keyboard and others.
        addDeadKey(ACCENT_STROKE, 'D', '\u0110');
        addDeadKey(ACCENT_STROKE, 'G', '\u01e4');
        addDeadKey(ACCENT_STROKE, 'H', '\u0126');
        addDeadKey(ACCENT_STROKE, 'I', '\u0197');
        addDeadKey(ACCENT_STROKE, 'L', '\u0141');
        addDeadKey(ACCENT_STROKE, 'O', '\u00d8');
        addDeadKey(ACCENT_STROKE, 'T', '\u0166');
        addDeadKey(ACCENT_STROKE, 'd', '\u0111');
        addDeadKey(ACCENT_STROKE, 'g', '\u01e5');
        addDeadKey(ACCENT_STROKE, 'h', '\u0127');
        addDeadKey(ACCENT_STROKE, 'i', '\u0268');
        addDeadKey(ACCENT_STROKE, 'l', '\u0142');
        addDeadKey(ACCENT_STROKE, 'o', '\u00f8');
        addDeadKey(ACCENT_STROKE, 't', '\u0167');
    }

    private static void addDeadKey(int accent, int c, int result) {
        final int combining = sAccentToCombining.get(accent);
        if (combining == 0) {
            throw new IllegalStateException("Invalid dead key declaration.");
        }
        final int combination = (combining << 16) | c;
        sDeadKeyCache.put(combination, result);
    }

    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 long mPtr;

    private static native long nativeReadFromParcel(Parcel in);
    private static native void nativeWriteToParcel(long ptr, Parcel out);
    private static native void nativeDispose(long ptr);

    private static native char nativeGetCharacter(long ptr, int keyCode, int metaState);
    private static native boolean nativeGetFallbackAction(long ptr, int keyCode, int metaState,
            FallbackAction outFallbackAction);
    private static native char nativeGetNumber(long ptr, int keyCode);
    private static native char nativeGetMatch(long ptr, int keyCode, char[] chars, int metaState);
    private static native char nativeGetDisplayLabel(long ptr, int keyCode);
    private static native int nativeGetKeyboardType(long ptr);
    private static native KeyEvent[] nativeGetEvents(long 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.");
        }
    }

    // Called from native
    @UnsupportedAppUsage
    private KeyCharacterMap(long ptr) {
        mPtr = ptr;
    }

    @Override
    protected void finalize() throws Throwable {
        if (mPtr != 0) {
            nativeDispose(mPtr);
            mPtr = 0;
        }
    }

    /**
     * Loads the key character maps for the keyboard with the specified device id.
     *
     * @param deviceId The device id of the keyboard.
     * @return The associated key character map.
     * @throws {@link UnavailableException} if the key character map
     * could not be loaded because it was malformed or the default key character map
     * is missing from the system.
     */
    public static KeyCharacterMap load(int deviceId) {
        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 inputDevice.getKeyCharacterMap();
    }

    /**
     * Gets the Unicode character generated by the specified key and meta
     * key state combination.
     * <p>
     * Returns the Unicode character that the specified key would produce
     * when the specified meta bits (see {@link MetaKeyKeyListener})
     * were active.
     * </p><p>
     * Returns 0 if the key is not one that is used to type Unicode
     * characters.
     * </p><p>
     * If the return value has bit {@link #COMBINING_ACCENT} set, the
     * key is a "dead key" that should be combined with another to
     * actually produce a character -- see {@link #getDeadChar} --
     * after masking with {@link #COMBINING_ACCENT_MASK}.
     * </p>
     *
     * @param keyCode The key code.
     * @param metaState The meta key modifier state.
     * @return The associated character or combining accent, or 0 if none.
     */
    public int get(int keyCode, int metaState) {
        metaState = KeyEvent.normalizeMetaState(metaState);
        char ch = nativeGetCharacter(mPtr, keyCode, metaState);

        int map = sCombiningToAccent.get(ch);
        if (map != 0) {
            return map | COMBINING_ACCENT;
        } else {
            return ch;
        }
    }

    /**
     * Gets the fallback action to perform if the application does not
     * handle the specified key.
     * <p>
     * When an application does not handle a particular key, the system may
     * translate the key to an alternate fallback key (specified in the
     * fallback action) and dispatch it to the application.
     * The event containing the fallback key is flagged
     * with {@link KeyEvent#FLAG_FALLBACK}.
     * </p>
     *
     * @param keyCode The key code.
     * @param metaState The meta key modifier state.
     * @return The fallback action, or null if none.  Remember to recycle the fallback action.
     *
     * @hide
     */
    public FallbackAction getFallbackAction(int keyCode, int metaState) {
        FallbackAction action = FallbackAction.obtain();
        metaState = KeyEvent.normalizeMetaState(metaState);
        if (nativeGetFallbackAction(mPtr, keyCode, metaState, action)) {
            action.metaState = KeyEvent.normalizeMetaState(action.metaState);
            return action;
        }
        action.recycle();
        return null;
    }

    /**
     * Gets the number or symbol associated with the key.
     * <p>
     * The character value is returned, not the numeric value.
     * If the key is not a number, but is a symbol, the symbol is retuned.
     * </p><p>
     * This method is intended to to support dial pads and other numeric or
     * symbolic entry on keyboards where certain keys serve dual function
     * as alphabetic and symbolic keys.  This method returns the number
     * or symbol associated with the key independent of whether the user
     * has pressed the required modifier.
     * </p><p>
     * For example, on one particular keyboard the keys on the top QWERTY row generate
     * numbers when ALT is pressed such that ALT-Q maps to '1'.  So for that keyboard
     * when {@link #getNumber} is called with {@link KeyEvent#KEYCODE_Q} it returns '1'
     * so that the user can type numbers without pressing ALT when it makes sense.
     * </p>
     *
     * @param keyCode The key code.
     * @return The associated numeric or symbolic character, or 0 if none.
     */
    public char getNumber(int keyCode) {
        return nativeGetNumber(mPtr, keyCode);
    }

    /**
     * Gets the first character in the character array that can be generated
     * by the specified key code.
     * <p>
     * This is a convenience function that returns the same value as
     * {@link #getMatch(int,char[],int) getMatch(keyCode, chars, 0)}.
     * </p>
     *
     * @param keyCode The keycode.
     * @param chars The array of matching characters to consider.
     * @return The matching associated character, or 0 if none.
     * @throws {@link IllegalArgumentException} if the passed array of characters is null.
     */
    public char getMatch(int keyCode, char[] chars) {
        return getMatch(keyCode, chars, 0);
    }

    /**
     * Gets the first character in the character array that can be generated
     * by the specified key code.  If there are multiple choices, prefers
     * the one that would be generated with the specified meta key modifier state.
     *
     * @param keyCode The key code.
     * @param chars The array of matching characters to consider.
     * @param metaState The preferred meta key modifier state.
     * @return The matching associated character, or 0 if none.
     * @throws {@link IllegalArgumentException} if the passed array of characters is null.
     */
    public char getMatch(int keyCode, char[] chars, int metaState) {
        if (chars == null) {
            throw new IllegalArgumentException("chars must not be null.");
        }

        metaState = KeyEvent.normalizeMetaState(metaState);
        return nativeGetMatch(mPtr, keyCode, chars, metaState);
    }

    /**
     * Gets the primary character for this key.
     * In other words, the label that is physically printed on it.
     *
     * @param keyCode The key code.
     * @return The display label character, or 0 if none (eg. for non-printing keys).
     */
    public char getDisplayLabel(int keyCode) {
        return nativeGetDisplayLabel(mPtr, keyCode);
    }

    /**
     * Get the character that is produced by combining the dead key producing accent
     * with the key producing character c.
     * For example, getDeadChar('`', 'e') returns &egrave;.
     * getDeadChar('^', ' ') returns '^' and getDeadChar('^', '^') returns '^'.
     *
     * @param accent The accent character.  eg. '`'
     * @param c The basic character.
     * @return The combined character, or 0 if the characters cannot be combined.
     */
    public static int getDeadChar(int accent, int c) {
        if (c == accent || CHAR_SPACE == c) {
            // The same dead character typed twice or a dead character followed by a
            // space should both produce the non-combining version of the combining char.
            // In this case we don't even need to compute the combining character.
            return accent;
        }

        int combining = sAccentToCombining.get(accent);
        if (combining == 0) {
            return 0;
        }

        final int combination = (combining << 16) | c;
        int combined;
        synchronized (sDeadKeyCache) {
            combined = sDeadKeyCache.get(combination, -1);
            if (combined == -1) {
                sDeadKeyBuilder.setLength(0);
                sDeadKeyBuilder.append((char)c);
                sDeadKeyBuilder.append((char)combining);
                String result = Normalizer.normalize(sDeadKeyBuilder, Normalizer.Form.NFC);
                combined = result.codePointCount(0, result.length()) == 1
                        ? result.codePointAt(0) : 0;
                sDeadKeyCache.put(combination, combined);
            }
        }
        return combined;
    }

    /**
     * Describes the character mappings associated with a key.
     *
     * @deprecated instead use {@link KeyCharacterMap#getDisplayLabel(int)},
     * {@link KeyCharacterMap#getNumber(int)} and {@link KeyCharacterMap#get(int, int)}.
     */
    @Deprecated
    public static class KeyData {
        public static final int META_LENGTH = 4;

        /**
         * The display label (see {@link #getDisplayLabel}).
         */
        public char displayLabel;
        /**
         * The "number" value (see {@link #getNumber}).
         */
        public char number;
        /**
         * The character that will be generated in various meta states
         * (the same ones used for {@link #get} and defined as
         * {@link KeyEvent#META_SHIFT_ON} and {@link KeyEvent#META_ALT_ON}).
         *      <table>
         *          <tr><th>Index</th><th align="left">Value</th></tr>
         *          <tr><td>0</td><td>no modifiers</td></tr>
         *          <tr><td>1</td><td>caps</td></tr>
         *          <tr><td>2</td><td>alt</td></tr>
         *          <tr><td>3</td><td>caps + alt</td></tr>
         *      </table>
         */
        public char[] meta = new char[META_LENGTH];
    }

    /**
     * Get the character conversion data for a given key code.
     *
     * @param keyCode The keyCode to query.
     * @param results A {@link KeyData} instance that will be filled with the results.
     * @return True if the key was mapped.  If the key was not mapped, results is not modified.
     *
     * @deprecated instead use {@link KeyCharacterMap#getDisplayLabel(int)},
     * {@link KeyCharacterMap#getNumber(int)} or {@link KeyCharacterMap#get(int, int)}.
     */
    @Deprecated
    public boolean getKeyData(int keyCode, KeyData results) {
        if (results.meta.length < KeyData.META_LENGTH) {
            throw new IndexOutOfBoundsException(
                    "results.meta.length must be >= " + KeyData.META_LENGTH);
        }

        char displayLabel = nativeGetDisplayLabel(mPtr, keyCode);
        if (displayLabel == 0) {
            return false;
        }

        results.displayLabel = displayLabel;
        results.number = nativeGetNumber(mPtr, keyCode);
        results.meta[0] = nativeGetCharacter(mPtr, keyCode, 0);
        results.meta[1] = nativeGetCharacter(mPtr, keyCode, KeyEvent.META_SHIFT_ON);
        results.meta[2] = nativeGetCharacter(mPtr, keyCode, KeyEvent.META_ALT_ON);
        results.meta[3] = nativeGetCharacter(mPtr, keyCode,
                KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
        return true;
    }

    /**
     * Get an array of KeyEvent objects that if put into the input stream
     * could plausibly generate the provided sequence of characters.  It is
     * not guaranteed that the sequence is the only way to generate these
     * events or that it is optimal.
     * <p>
     * This function is primarily offered for instrumentation and testing purposes.
     * It may fail to map characters to key codes.  In particular, the key character
     * map for the {@link #BUILT_IN_KEYBOARD built-in keyboard} device id may be empty.
     * Consider using the key character map associated with the
     * {@link #VIRTUAL_KEYBOARD virtual keyboard} device id instead.
     * </p><p>
     * For robust text entry, do not use this function.  Instead construct a
     * {@link KeyEvent} with action code {@link KeyEvent#ACTION_MULTIPLE} that contains
     * the desired string using {@link KeyEvent#KeyEvent(long, String, int, int)}.
     * </p>
     *
     * @param chars The sequence of characters to generate.
     * @return An array of {@link KeyEvent} objects, or null if the given char array
     *         can not be generated using the current key character map.
     * @throws {@link IllegalArgumentException} if the passed array of characters is null.
     */
    public KeyEvent[] getEvents(char[] chars) {
        if (chars == null) {
            throw new IllegalArgumentException("chars must not be null.");
        }
        return nativeGetEvents(mPtr, chars);
    }

    /**
     * Returns true if the specified key produces a glyph.
     *
     * @param keyCode The key code.
     * @return True if the key is a printing key.
     */
    public boolean isPrintingKey(int keyCode) {
        int type = Character.getType(nativeGetDisplayLabel(mPtr, keyCode));

        switch (type)
        {
            case Character.SPACE_SEPARATOR:
            case Character.LINE_SEPARATOR:
            case Character.PARAGRAPH_SEPARATOR:
            case Character.CONTROL:
            case Character.FORMAT:
                return false;
            default:
                return true;
        }
    }

    /**
     * Gets the keyboard type.
     * Returns {@link #NUMERIC}, {@link #PREDICTIVE}, {@link #ALPHA}, {@link #FULL}
     * or {@link #SPECIAL_FUNCTION}.
     * <p>
     * Different keyboard types have different semantics.  Refer to the documentation
     * associated with the keyboard type constants for details.
     * </p>
     *
     * @return The keyboard type.
     */
    public int getKeyboardType() {
        return nativeGetKeyboardType(mPtr);
    }

    /**
     * Gets a constant that describes the behavior of this keyboard's modifier keys
     * such as {@link KeyEvent#KEYCODE_SHIFT_LEFT}.
     * <p>
     * Currently there are two behaviors that may be combined:
     * </p>
     * <ul>
     * <li>Chorded behavior: When the modifier key is pressed together with one or more
     * character keys, the keyboard inserts the modified keys and
     * then resets the modifier state when the modifier key is released.</li>
     * <li>Toggled behavior: When the modifier key is pressed and released on its own
     * it first toggles into a latched state.  When latched, the modifier will apply
     * to next character key that is pressed and will then reset itself to the initial state.
     * If the modifier is already latched and the modifier key is pressed and release on
     * its own again, then it toggles into a locked state.  When locked, the modifier will
     * apply to all subsequent character keys that are pressed until unlocked by pressing
     * the modifier key on its own one more time to reset it to the initial state.
     * Toggled behavior is useful for small profile keyboards designed for thumb typing.
     * </ul>
     * <p>
     * This function currently returns {@link #MODIFIER_BEHAVIOR_CHORDED} when the
     * {@link #getKeyboardType() keyboard type} is {@link #FULL} or {@link #SPECIAL_FUNCTION} and
     * {@link #MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED} otherwise.
     * In the future, the function may also take into account global keyboard
     * accessibility settings, other user preferences, or new device capabilities.
     * </p>
     *
     * @return The modifier behavior for this keyboard.
     *
     * @see #MODIFIER_BEHAVIOR_CHORDED
     * @see #MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED
     */
    public int getModifierBehavior() {
        switch (getKeyboardType()) {
            case FULL:
            case SPECIAL_FUNCTION:
                return MODIFIER_BEHAVIOR_CHORDED;
            default:
                return MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED;
        }
    }

    /**
     * Queries the framework about whether any physical keys exist on the
     * any keyboard attached to the device that are capable of producing the given key code.
     *
     * @param keyCode The key code to query.
     * @return True if at least one attached keyboard supports the specified key code.
     */
    public static boolean deviceHasKey(int keyCode) {
        return InputManager.getInstance().deviceHasKeys(new int[] { keyCode })[0];
    }

    /**
     * Queries the framework about whether any physical keys exist on the
     * any keyboard attached to the device that are capable of producing the given
     * array of key codes.
     *
     * @param keyCodes The array of key codes to query.
     * @return A new array of the same size as the key codes array whose elements
     * are set to true if at least one attached keyboard supports the corresponding key code
     * at the same index in the key codes array.
     */
    public static boolean[] deviceHasKeys(int[] 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;
    }

    /**
     * Thrown by {@link KeyCharacterMap#load} when a key character map could not be loaded.
     */
    public static class UnavailableException extends AndroidRuntimeException {
        public UnavailableException(String msg) {
            super(msg);
        }
    }

    /**
     * Specifies a substitute key code and meta state as a fallback action
     * for an unhandled key.
     * @hide
     */
    public static final class FallbackAction {
        private static final int MAX_RECYCLED = 10;
        private static final Object sRecycleLock = new Object();
        private static FallbackAction sRecycleBin;
        private static int sRecycledCount;

        private FallbackAction next;

        @UnsupportedAppUsage
        public int keyCode;
        @UnsupportedAppUsage
        public int metaState;

        private FallbackAction() {
        }

        public static FallbackAction obtain() {
            final FallbackAction target;
            synchronized (sRecycleLock) {
                if (sRecycleBin == null) {
                    target = new FallbackAction();
                } else {
                    target = sRecycleBin;
                    sRecycleBin = target.next;
                    sRecycledCount--;
                    target.next = null;
                }
            }
            return target;
        }

        public void recycle() {
            synchronized (sRecycleLock) {
                if (sRecycledCount < MAX_RECYCLED) {
                    next = sRecycleBin;
                    sRecycleBin = this;
                    sRecycledCount += 1;
                } else {
                    next = null;
                }
            }
        }
    }
}
