1dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard/*
2dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard * Copyright (C) 2011 The Android Open Source Project
3dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard *
48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License.
68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at
7dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard *
88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard *
10dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard * Unless required by applicable law or agreed to in writing, software
118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and
148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License.
15dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard */
16dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard
17dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalardpackage com.android.inputmethod.latin;
18dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard
199342484e8d573a40f470b6a593df31c602fa4076Ken Wakasaimport static com.android.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
209342484e8d573a40f470b6a593df31c602fa4076Ken Wakasaimport static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
219342484e8d573a40f470b6a593df31c602fa4076Ken Wakasaimport static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
223ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka
23644c8b7c96627199c13297082e4566adae159bf3Jean Chalardimport android.text.InputType;
24644c8b7c96627199c13297082e4566adae159bf3Jean Chalardimport android.util.Log;
25dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalardimport android.view.inputmethod.EditorInfo;
26dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard
274beeb9253a06482299e0c67467531d30436a02fcJean Chalardimport com.android.inputmethod.latin.common.StringUtils;
28e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.InputTypeUtils;
29e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasa
3006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaokaimport java.util.ArrayList;
3106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaokaimport java.util.Arrays;
3206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
33dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard/**
34dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard * Class to hold attributes of the input field.
35dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard */
36a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class InputAttributes {
37dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard    private final String TAG = InputAttributes.class.getSimpleName();
38dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard
391404c1af850236da4fe4ed3825b70cb228a1da5bJean Chalard    final public String mTargetApplicationPackageName;
40644c8b7c96627199c13297082e4566adae159bf3Jean Chalard    final public boolean mInputTypeNoAutoCorrect;
41ce78a2d8ab7630cff509c2b21b4b11abd8db4795Tadashi G. Takaoka    final public boolean mIsPasswordField;
422e32e37d5bf95743eb56ef1b9560ffc5032bccf3Tadashi G. Takaoka    final public boolean mShouldShowSuggestions;
43644c8b7c96627199c13297082e4566adae159bf3Jean Chalard    final public boolean mApplicationSpecifiedCompletionOn;
44ec60d60078b4837b657dc207bdbde1748749199eJean Chalard    final public boolean mShouldInsertSpacesAutomatically;
450351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka    final public boolean mShouldShowVoiceInputKey;
4695b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden    /**
4795b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden     * Whether the floating gesture preview should be disabled. If true, this should override the
4895b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden     * corresponding keyboard settings preference, always suppressing the floating preview text.
4995b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden     * {@link com.android.inputmethod.latin.settings.SettingsValues#mGestureFloatingPreviewTextEnabled}
5095b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden     */
5195b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden    final public boolean mDisableGestureFloatingPreviewText;
527aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard    final public boolean mIsGeneralTextInput;
53e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard    final private int mInputType;
543ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka    final private EditorInfo mEditorInfo;
553ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka    final private String mPackageNameForPrivateImeOptions;
56644c8b7c96627199c13297082e4566adae159bf3Jean Chalard
573ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka    public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode,
583ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka            final String packageNameForPrivateImeOptions) {
593ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        mEditorInfo = editorInfo;
603ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        mPackageNameForPrivateImeOptions = packageNameForPrivateImeOptions;
611404c1af850236da4fe4ed3825b70cb228a1da5bJean Chalard        mTargetApplicationPackageName = null != editorInfo ? editorInfo.packageName : null;
62752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard        final int inputType = null != editorInfo ? editorInfo.inputType : 0;
63752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard        final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
64e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard        mInputType = inputType;
659fb27977141bdccc3bbd0cacc71ba6ba8d7a71dcTadashi G. Takaoka        mIsPasswordField = InputTypeUtils.isPasswordInputType(inputType)
669fb27977141bdccc3bbd0cacc71ba6ba8d7a71dcTadashi G. Takaoka                || InputTypeUtils.isVisiblePasswordInputType(inputType);
67752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard        if (inputClass != InputType.TYPE_CLASS_TEXT) {
68752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            // If we are not looking at a TYPE_CLASS_TEXT field, the following strange
69752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            // cases may arise, so we do a couple sanity checks for them. If it's a
70752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            // TYPE_CLASS_TEXT field, these special cases cannot happen, by construction
71752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            // of the flags.
72752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            if (null == editorInfo) {
73752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard                Log.w(TAG, "No editor info for this field. Bug?");
74752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            } else if (InputType.TYPE_NULL == inputType) {
75644c8b7c96627199c13297082e4566adae159bf3Jean Chalard                // TODO: We should honor TYPE_NULL specification.
76644c8b7c96627199c13297082e4566adae159bf3Jean Chalard                Log.i(TAG, "InputType.TYPE_NULL is specified");
77752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            } else if (inputClass == 0) {
7880b66bb166f7f45adfcadcb84788477df9930828Jean Chalard                // TODO: is this check still necessary?
79644c8b7c96627199c13297082e4566adae159bf3Jean Chalard                Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x"
802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa                        + " imeOptions=0x%08x", inputType, editorInfo.imeOptions));
81644c8b7c96627199c13297082e4566adae159bf3Jean Chalard            }
822e32e37d5bf95743eb56ef1b9560ffc5032bccf3Tadashi G. Takaoka            mShouldShowSuggestions = false;
83752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            mInputTypeNoAutoCorrect = false;
84752d8cc4fc8550e5ec4eee921f5d611c49f57497Jean Chalard            mApplicationSpecifiedCompletionOn = false;
85ec60d60078b4837b657dc207bdbde1748749199eJean Chalard            mShouldInsertSpacesAutomatically = false;
860351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka            mShouldShowVoiceInputKey = false;
8795b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden            mDisableGestureFloatingPreviewText = false;
887aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard            mIsGeneralTextInput = false;
8906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return;
9006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        }
9106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // inputClass == InputType.TYPE_CLASS_TEXT
9206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final int variation = inputType & InputType.TYPE_MASK_VARIATION;
9306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final boolean flagNoSuggestions =
9406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
9506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final boolean flagMultiLine =
9606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE);
9706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final boolean flagAutoCorrect =
9806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
9906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final boolean flagAutoComplete =
10006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
101644c8b7c96627199c13297082e4566adae159bf3Jean Chalard
10206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // TODO: Have a helper method in InputTypeUtils
10306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // Make sure that passwords are not displayed in {@link SuggestionStripView}.
1042e32e37d5bf95743eb56ef1b9560ffc5032bccf3Tadashi G. Takaoka        final boolean shouldSuppressSuggestions = mIsPasswordField
10506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || InputTypeUtils.isEmailVariation(variation)
10606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || InputType.TYPE_TEXT_VARIATION_URI == variation
10706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || InputType.TYPE_TEXT_VARIATION_FILTER == variation
10806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || flagNoSuggestions
10906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || flagAutoComplete;
1102e32e37d5bf95743eb56ef1b9560ffc5032bccf3Tadashi G. Takaoka        mShouldShowSuggestions = !shouldSuppressSuggestions;
111644c8b7c96627199c13297082e4566adae159bf3Jean Chalard
11206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
11306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
1140351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka        final boolean noMicrophone = mIsPasswordField
115bfabac449d0b529ee22887aa198a34fdf04b3bebTadashi G. Takaoka                || InputTypeUtils.isEmailVariation(variation)
1160351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka                || InputType.TYPE_TEXT_VARIATION_URI == variation
1170351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka                || hasNoMicrophoneKeyOption();
1180351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka        mShouldShowVoiceInputKey = !noMicrophone;
1190351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka
12095b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden        mDisableGestureFloatingPreviewText = InputAttributes.inPrivateImeOptions(
12195b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden                mPackageNameForPrivateImeOptions, NO_FLOATING_GESTURE_PREVIEW, editorInfo);
12295b7bd3ba5bc76dedb964f0fb9a858e072ea4e91David Faden
12306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // If it's a browser edit field and auto correct is not ON explicitly, then
12406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // disable auto correction, but keep suggestions on.
12506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // If NO_SUGGESTIONS is set, don't do prediction.
12606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        // If it's not multiline and the autoCorrect flag is not set, then don't correct
12706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        mInputTypeNoAutoCorrect =
12806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT && !flagAutoCorrect)
12906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || flagNoSuggestions
13006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                || (!flagAutoCorrect && !flagMultiLine);
13106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
13206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
1337aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard
1347aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard        // If we come here, inputClass is always TYPE_CLASS_TEXT
1357aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard        mIsGeneralTextInput = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != variation
1367aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_PASSWORD != variation
1377aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_PHONETIC != variation
1387aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_URI != variation
1397aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != variation
1407aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != variation
1417aa47cb3748d82b6f8bf3713c3c9e05b3fca8979Jean Chalard                && InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != variation;
142dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard    }
1436fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard
144de814ec0ec7f5b7674c5bb95694813c35af10fd6Jean Chalard    public boolean isTypeNull() {
145de814ec0ec7f5b7674c5bb95694813c35af10fd6Jean Chalard        return InputType.TYPE_NULL == mInputType;
146de814ec0ec7f5b7674c5bb95694813c35af10fd6Jean Chalard    }
147de814ec0ec7f5b7674c5bb95694813c35af10fd6Jean Chalard
148e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard    public boolean isSameInputType(final EditorInfo editorInfo) {
149e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard        return editorInfo.inputType == mInputType;
150e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard    }
151e234aed4288efd7b4336f3755a958c25a1540b98Jean Chalard
1520351b816327ebddef0c4c1f95834645a4fab96feTadashi G. Takaoka    private boolean hasNoMicrophoneKeyOption() {
1533ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        @SuppressWarnings("deprecation")
1543ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
1553ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka                null, NO_MICROPHONE_COMPAT, mEditorInfo);
1563ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        final boolean noMicrophone = InputAttributes.inPrivateImeOptions(
1573ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka                mPackageNameForPrivateImeOptions, NO_MICROPHONE, mEditorInfo);
1583ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka        return noMicrophone || deprecatedNoMicrophone;
1593ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka    }
1603ca65c8fd56724a7b4b3440bccf613e5a1a17513Tadashi G. Takaoka
161728d1c884e99e1fd25aa253b5ad30dbdb046ad5fsatok    @SuppressWarnings("unused")
1623f65960e1614e01d882c15f153d9c5fc5fec5016Jean Chalard    private void dumpFlags(final int inputType) {
1633f65960e1614e01d882c15f153d9c5fc5fec5016Jean Chalard        final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
16406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final String inputClassString = toInputClassString(inputClass);
16506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final String variationString = toVariationString(
16606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka                inputClass, inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
16706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        final String flagsString = toFlagsString(inputType & InputType.TYPE_MASK_FLAGS);
16806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        Log.i(TAG, "Input class: " + inputClassString);
16906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        Log.i(TAG, "Variation: " + variationString);
17006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        Log.i(TAG, "Flags: " + flagsString);
17106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
17206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
17306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toInputClassString(final int inputClass) {
17406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        switch (inputClass) {
17506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_TEXT:
17606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_CLASS_TEXT";
17706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_PHONE:
17806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_CLASS_PHONE";
17906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_NUMBER:
18006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_CLASS_NUMBER";
18106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_DATETIME:
18206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_CLASS_DATETIME";
18306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        default:
18406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return String.format("unknownInputClass<0x%08x>", inputClass);
18506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        }
18606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
18706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
18806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toVariationString(final int inputClass, final int variation) {
18906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        switch (inputClass) {
19006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_TEXT:
19106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return toTextVariationString(variation);
19206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_NUMBER:
19306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return toNumberVariationString(variation);
19406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_CLASS_DATETIME:
19506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return toDatetimeVariationString(variation);
19606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        default:
19706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "";
1984d0fa3177994fd52297819b69f98ebd272eb800fJean Chalard        }
19906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
20006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
20106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toTextVariationString(final int variation) {
20206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        switch (variation) {
20306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
20406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
20506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
20606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
20706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_FILTER:
20806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_FILTER";
20906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE:
21006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_LONG_MESSAGE";
21106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_NORMAL:
21206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_NORMAL";
21306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_PASSWORD:
21406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_PASSWORD";
21506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_PERSON_NAME:
21606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_PERSON_NAME";
21706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_PHONETIC:
21806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_PHONETIC";
21906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
22006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_POSTAL_ADDRESS";
22106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE:
22206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_SHORT_MESSAGE";
22306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_URI:
22406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_URI";
22506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
22606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD";
22706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT:
22806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT";
22906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
23006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS";
23106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD:
23206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_TEXT_VARIATION_WEB_PASSWORD";
23306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        default:
23406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return String.format("unknownVariation<0x%08x>", variation);
23506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        }
23606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
23706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
23806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toNumberVariationString(final int variation) {
23906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        switch (variation) {
24006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_NUMBER_VARIATION_NORMAL:
24106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_NUMBER_VARIATION_NORMAL";
24206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_NUMBER_VARIATION_PASSWORD:
24306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_NUMBER_VARIATION_PASSWORD";
24406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        default:
24506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return String.format("unknownVariation<0x%08x>", variation);
24606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        }
24706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
24806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
24906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toDatetimeVariationString(final int variation) {
25006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        switch (variation) {
25106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_DATETIME_VARIATION_NORMAL:
25206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_DATETIME_VARIATION_NORMAL";
25306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_DATETIME_VARIATION_DATE:
25406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_DATETIME_VARIATION_DATE";
25506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        case InputType.TYPE_DATETIME_VARIATION_TIME:
25606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return "TYPE_DATETIME_VARIATION_TIME";
25706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        default:
25806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            return String.format("unknownVariation<0x%08x>", variation);
25906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        }
26006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    }
26106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka
26206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka    private static String toFlagsString(final int flags) {
263a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka        final ArrayList<String> flagsArray = new ArrayList<>();
26406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS))
26506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_NO_SUGGESTIONS");
26606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_MULTI_LINE))
26706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_MULTI_LINE");
26806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE))
26906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_IME_MULTI_LINE");
27006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_WORDS))
27106fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_CAP_WORDS");
27206fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES))
27306fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_CAP_SENTENCES");
27406fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS))
27506fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_CAP_CHARACTERS");
27606fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT))
27706fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_AUTO_CORRECT");
27806fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE))
27906fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka            flagsArray.add("TYPE_TEXT_FLAG_AUTO_COMPLETE");
28006fbfc4951e69a2a5eae712fbfdab761576da9eaTadashi G. Takaoka        return flagsArray.isEmpty() ? "" : Arrays.toString(flagsArray.toArray());
2813f65960e1614e01d882c15f153d9c5fc5fec5016Jean Chalard    }
2823f65960e1614e01d882c15f153d9c5fc5fec5016Jean Chalard
2836fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard    // Pretty print
2846fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard    @Override
2856fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard    public String toString() {
286affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka        return String.format(
287affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                "%s: inputType=0x%08x%s%s%s%s%s targetApp=%s\n", getClass().getSimpleName(),
288affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                mInputType,
289affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                (mInputTypeNoAutoCorrect ? " noAutoCorrect" : ""),
290affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                (mIsPasswordField ? " password" : ""),
2912e32e37d5bf95743eb56ef1b9560ffc5032bccf3Tadashi G. Takaoka                (mShouldShowSuggestions ? " shouldShowSuggestions" : ""),
292affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                (mApplicationSpecifiedCompletionOn ? " appSpecified" : ""),
293affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                (mShouldInsertSpacesAutomatically ? " insertSpaces" : ""),
294affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka                mTargetApplicationPackageName);
2956fa003ee234c6e2ca6cd9ec555221ac5c71a5405Jean Chalard    }
296344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka
297affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka    public static boolean inPrivateImeOptions(final String packageName, final String key,
298affdd364232549d2062fc180f924f5b6496c26fdTadashi G. Takaoka            final EditorInfo editorInfo) {
299344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka        if (editorInfo == null) return false;
3002fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        final String findingKey = (packageName != null) ? packageName + "." + key : key;
301c47bc30db84ecdf340a1faffafa2e9a9d5dd9d6aTadashi G. Takaoka        return StringUtils.containsInCommaSplittableText(findingKey, editorInfo.privateImeOptions);
302344af156744c6866090fb70f151efd66668c1e20Tadashi G. Takaoka    }
303dc9d0fcc11f0886296c6eb325fe4f71beb87ff4cJean Chalard}
304