PasswordEntryKeyboardHelper.java revision 79a02b15850347a2e932272b21b14c0c2b3faf50
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 Google Inc.
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * License for the specific language governing permissions and limitations under
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.inputmethodservice.Keyboard;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.inputmethodservice.KeyboardView;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
2534385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.os.SystemClock;
2634385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.os.Vibrator;
2734385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.provider.Settings;
28e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwoodimport android.util.Log;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyCharacterMap;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewRootImpl;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PasswordEntryKeyboardHelper implements OnKeyboardActionListener {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int KEYBOARD_MODE_ALPHA = 0;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int KEYBOARD_MODE_NUMERIC = 1;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int KEYBOARD_STATE_NORMAL = 0;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int KEYBOARD_STATE_SHIFTED = 1;
42118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu    private static final int KEYBOARD_STATE_CAPSLOCK = 2;
43118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu    private static final String TAG = "PasswordEntryKeyboardHelper";
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mKeyboardMode = KEYBOARD_MODE_ALPHA;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mKeyboardState = KEYBOARD_STATE_NORMAL;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PasswordEntryKeyboard mQwertyKeyboard;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PasswordEntryKeyboard mQwertyKeyboardShifted;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PasswordEntryKeyboard mSymbolsKeyboard;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PasswordEntryKeyboard mSymbolsKeyboardShifted;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PasswordEntryKeyboard mNumericKeyboard;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mContext;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mTargetView;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private KeyboardView mKeyboardView;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private long[] mVibratePattern;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Vibrator mVibrator;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView) {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, keyboardView, targetView, true);
5954d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar    }
6054d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar
6154d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar    public PasswordEntryKeyboardHelper(Context context, KeyboardView keyboardView, View targetView,
6254d50089ee526110e42e0f8399660a012d9c6c1bIan McKellar            boolean useFullScreenWidth) {
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTargetView = targetView;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mKeyboardView = keyboardView;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useFullScreenWidth
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || mKeyboardView.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createKeyboards();
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            createKeyboardsWithSpecificSize(mKeyboardView.getLayoutParams().width,
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mKeyboardView.getLayoutParams().height);
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mKeyboardView.setOnKeyboardActionListener(this);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVibrator = new Vibrator();
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAlpha() {
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mKeyboardMode == KEYBOARD_MODE_ALPHA;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void createKeyboardsWithSpecificSize(int viewWidth, int viewHeight) {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumericKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_numeric,
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewWidth, viewHeight);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboard = new PasswordEntryKeyboard(mContext,
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_qwerty, R.id.mode_normal, viewWidth, viewHeight);
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboard.enableShiftLock();
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext,
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_qwerty_shifted,
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.id.mode_normal, viewWidth, viewHeight);
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted.enableShiftLock();
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted.setShifted(true); // always shifted.
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_symbols,
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                viewWidth, viewHeight);
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboard.enableShiftLock();
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext,
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_symbols_shift, viewWidth, viewHeight);
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted.enableShiftLock();
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted.setShifted(true); // always shifted
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void createKeyboards() {
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumericKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_numeric);
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboard = new PasswordEntryKeyboard(mContext,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_qwerty, R.id.mode_normal);
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboard.enableShiftLock();
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted = new PasswordEntryKeyboard(mContext,
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_qwerty_shifted,
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.id.mode_normal);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted.enableShiftLock();
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mQwertyKeyboardShifted.setShifted(true); // always shifted.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboard = new PasswordEntryKeyboard(mContext, R.xml.password_kbd_symbols);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboard.enableShiftLock();
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted = new PasswordEntryKeyboard(mContext,
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                R.xml.password_kbd_symbols_shift);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted.enableShiftLock();
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSymbolsKeyboardShifted.setShifted(true); // always shifted
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setKeyboardMode(int mode) {
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (mode) {
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KEYBOARD_MODE_ALPHA:
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardView.setKeyboard(mQwertyKeyboard);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardState = KEYBOARD_STATE_NORMAL;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final boolean visiblePassword = Settings.System.getInt(
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mContext.getContentResolver(),
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Settings.System.TEXT_SHOW_PASSWORD, 1) != 0;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final boolean enablePreview = false; // TODO: grab from configuration
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardView.setPreviewEnabled(visiblePassword && enablePreview);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KEYBOARD_MODE_NUMERIC:
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardView.setKeyboard(mNumericKeyboard);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardState = KEYBOARD_STATE_NORMAL;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardView.setPreviewEnabled(false); // never show popup for numeric keypad
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mKeyboardMode = mode;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void sendKeyEventsToTarget(int character) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Handler handler = mTargetView.getHandler();
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        KeyEvent[] events = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(
14871bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                new char[] { (char) character });
14971bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        if (events != null) {
15071bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy            final int N = events.length;
15171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy            for (int i=0; i<N; i++) {
15271bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                KeyEvent event = events[i];
15371bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                event = KeyEvent.changeFlags(event, event.getFlags()
15471bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                        | KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
15571bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY, event));
15671bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy            }
15771bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        }
15871bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy    }
159d073bfdb3a44f07ef5338306f9b9377532962290Matthew Xie
16071bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy    public void sendDownUpKeyEvents(int keyEventCode) {
16171bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        long eventTime = SystemClock.uptimeMillis();
16271bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        Handler handler = mTargetView.getHandler();
16371bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
16471bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyEventCode, 0, 0,
16571bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
16671bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                    KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0,
16971bfafc84af4b820748b12e1a1010b0dfa7bdea6zzy                        KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onKey(int primaryCode, int[] keyCodes) {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (primaryCode == Keyboard.KEYCODE_DELETE) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleBackspace();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleShift();
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (primaryCode == Keyboard.KEYCODE_CANCEL) {
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleClose();
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE && mKeyboardView != null) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleModeChange();
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleCharacter(primaryCode, keyCodes);
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Switch back to old keyboard if we're not in capslock mode
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mKeyboardState == KEYBOARD_STATE_SHIFTED) {
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // skip to the unlocked state
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mKeyboardState = KEYBOARD_STATE_CAPSLOCK;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleShift();
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets and enables vibrate pattern.  If id is 0 (or can't be loaded), vibrate is disabled.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param id resource id for array containing vibrate pattern.
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setVibratePattern(int id) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] tmpArray = null;
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            tmpArray = mContext.getResources().getIntArray(id);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Resources.NotFoundException e) {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (id != 0) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.e(TAG, "Vibrate pattern missing", e);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tmpArray == null) {
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVibratePattern = null;
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mVibratePattern = new long[tmpArray.length];
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < tmpArray.length; i++) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVibratePattern[i] = tmpArray[i];
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleModeChange() {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Keyboard current = mKeyboardView.getKeyboard();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Keyboard next = null;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (current == mQwertyKeyboard || current == mQwertyKeyboardShifted) {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            next = mSymbolsKeyboard;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (current == mSymbolsKeyboard || current == mSymbolsKeyboardShifted) {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            next = mQwertyKeyboard;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (next != null) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKeyboardView.setKeyboard(next);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mKeyboardState = KEYBOARD_STATE_NORMAL;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
231e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood    private void handleBackspace() {
232e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
235e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood    private void handleShift() {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mKeyboardView == null) {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
239e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        Keyboard current = mKeyboardView.getKeyboard();
240e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        PasswordEntryKeyboard next = null;
241e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        final boolean isAlphaMode = current == mQwertyKeyboard
242e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood                || current == mQwertyKeyboardShifted;
243e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        if (mKeyboardState == KEYBOARD_STATE_NORMAL) {
244e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            mKeyboardState = isAlphaMode ? KEYBOARD_STATE_SHIFTED : KEYBOARD_STATE_CAPSLOCK;
245e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            next = isAlphaMode ? mQwertyKeyboardShifted : mSymbolsKeyboardShifted;
246e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        } else if (mKeyboardState == KEYBOARD_STATE_SHIFTED) {
247e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            mKeyboardState = KEYBOARD_STATE_CAPSLOCK;
248e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            next = isAlphaMode ? mQwertyKeyboardShifted : mSymbolsKeyboardShifted;
249e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        } else if (mKeyboardState == KEYBOARD_STATE_CAPSLOCK) {
250e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            mKeyboardState = KEYBOARD_STATE_NORMAL;
251e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            next = isAlphaMode ? mQwertyKeyboard : mSymbolsKeyboard;
252e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        }
253e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        if (next != null) {
25434385d352da19805ae948215e2edbeedd16b7941Elliott Hughes            if (next != current) {
255118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu                mKeyboardView.setKeyboard(next);
256e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            }
257e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            next.setShiftLocked(mKeyboardState == KEYBOARD_STATE_CAPSLOCK);
258e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            mKeyboardView.setShifted(mKeyboardState != KEYBOARD_STATE_NORMAL);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void handleCharacter(int primaryCode, int[] keyCodes) {
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Maybe turn off shift if not in capslock mode.
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mKeyboardView.isShifted() && primaryCode != ' ' && primaryCode != '\n') {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            primaryCode = Character.toUpperCase(primaryCode);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sendKeyEventsToTarget(primaryCode);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
269118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu
270118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu    private void handleClose() {
271118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu
272118c85156a552440d41aaa396d42f5e938f6c38bZhihai Xu    }
273e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood
27434385d352da19805ae948215e2edbeedd16b7941Elliott Hughes    public void onPress(int primaryCode) {
275e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        if (mVibratePattern != null) {
276e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood            mVibrator.vibrate(mVibratePattern, -1);
277e7d309a929bf87a5752cd1fb2d48c72e47a671a2Mike Lockwood        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onRelease(int primaryCode) {
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onText(CharSequence text) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void swipeDown() {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void swipeLeft() {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void swipeRight() {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void swipeUp() {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project