diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
12 files changed, 197 insertions, 41 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 69fe6de9a..5aae010ac 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -793,12 +793,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @Override public void onStartInputView(final EditorInfo editorInfo, final boolean restarting) { mHandler.onStartInputView(editorInfo, restarting); + mStatsUtilsManager.onStartInputView(); } @Override public void onFinishInputView(final boolean finishingInput) { StatsUtils.onFinishInputView(); mHandler.onFinishInputView(finishingInput); + mStatsUtilsManager.onFinishInputView(); } @Override @@ -1491,7 +1493,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final boolean isEmptyApplicationSpecifiedCompletions = currentSettingsValues.isApplicationSpecifiedCompletionsOn() && suggestedWords.isEmpty(); - final boolean noSuggestionsFromDictionaries = (SuggestedWords.EMPTY == suggestedWords) + final boolean noSuggestionsFromDictionaries = suggestedWords.isEmpty() || suggestedWords.isPunctuationSuggestions() || isEmptyApplicationSpecifiedCompletions; final boolean isBeginningOfSentencePrediction = (suggestedWords.mInputStyle @@ -1518,7 +1520,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final OnGetSuggestedWordsCallback callback) { final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); if (keyboard == null) { - callback.onGetSuggestedWords(SuggestedWords.EMPTY); + callback.onGetSuggestedWords(SuggestedWords.getEmptyInstance()); return; } mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(), @@ -1526,10 +1528,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } @Override - public void showSuggestionStrip(final SuggestedWords sourceSuggestedWords) { - final SuggestedWords suggestedWords = - sourceSuggestedWords.isEmpty() ? SuggestedWords.EMPTY : sourceSuggestedWords; - if (SuggestedWords.EMPTY == suggestedWords) { + public void showSuggestionStrip(final SuggestedWords suggestedWords) { + if (suggestedWords.isEmpty()) { setNeutralSuggestionStrip(); } else { setSuggestedWords(suggestedWords); @@ -1537,7 +1537,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Cache the auto-correction in accessibility code so we can speak it if the user // touches a key that will insert it. AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords, - sourceSuggestedWords.mTypedWord); + suggestedWords.mTypedWord); } // Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener} @@ -1572,7 +1572,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void setNeutralSuggestionStrip() { final SettingsValues currentSettings = mSettings.getCurrent(); final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled - ? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList; + ? SuggestedWords.getEmptyInstance() + : currentSettings.mSpacingAndPunctuations.mSuggestPuncList; setSuggestedWords(neutralSuggestions); } diff --git a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java index 76d4f57da..1b7e8f96d 100644 --- a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java +++ b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java @@ -126,6 +126,13 @@ public class PrevWordsInfo { } } + public PrevWordsInfo getTrimmedPrevWordsInfo(final int maxPrevWordCount) { + final int newSize = Math.min(maxPrevWordCount, mPrevWordsInfo.length); + // TODO: Quit creating a new array. + final WordInfo[] prevWordsInfo = Arrays.copyOf(mPrevWordsInfo, newSize); + return new PrevWordsInfo(prevWordsInfo); + } + public int getPrevWordCount() { return mPrevWordsInfo.length; } diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 3eefafc1f..e6fd43a07 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -45,7 +45,7 @@ public class SuggestedWords { public static final int MAX_SUGGESTIONS = 18; private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = new ArrayList<>(0); - public static final SuggestedWords EMPTY = new SuggestedWords( + private static final SuggestedWords EMPTY = new SuggestedWords( EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */, false /* isObsoleteSuggestions */, INPUT_STYLE_NONE); @@ -196,6 +196,10 @@ public class SuggestedWords { return result; } + public static final SuggestedWords getEmptyInstance() { + return SuggestedWords.EMPTY; + } + // Should get rid of the first one (what the user typed previously) from suggestions // and replace it with what the user currently typed. public static ArrayList<SuggestedWordInfo> getTypedWordAndPreviousSuggestions( diff --git a/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java b/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java new file mode 100644 index 000000000..9445ce4c3 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/accounts/AccountsChangedReceiver.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 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 com.android.inputmethod.latin.accounts; + +import android.accounts.AccountManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.latin.settings.Settings; + +/** + * {@link BroadcastReceiver} for {@link AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION}. + */ +public class AccountsChangedReceiver extends BroadcastReceiver { + static final String TAG = "AccountsChangedReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + if (!AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) { + Log.w(TAG, "Received unknown broadcast: " + intent); + return; + } + + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + final String currentAccount = prefs.getString(Settings.PREF_ACCOUNT_NAME, null); + if (currentAccount != null) { + final String[] accounts = getAccountsForLogin(context); + boolean accountFound = false; + for (String account : accounts) { + if (TextUtils.equals(currentAccount, account)) { + accountFound = true; + break; + } + } + // The current account was not found in the list of accounts, remove it. + if (!accountFound) { + Log.i(TAG, "The current account was removed from the system: " + currentAccount); + prefs.edit() + .remove(Settings.PREF_ACCOUNT_NAME) + .apply(); + } + } + } + + /** + * Helper method to help test this receiver. + */ + @UsedForTesting + protected String[] getAccountsForLogin(Context context) { + return LoginAccountUtils.getAccountsForLogin(context); + } +} diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 8eccd5cee..46427e5ca 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -86,7 +86,7 @@ public final class InputLogic { // Current space state of the input method. This can be any of the above constants. private int mSpaceState; // Never null - public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; + public SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance(); public final Suggest mSuggest; private final DictionaryFacilitator mDictionaryFacilitator; @@ -145,13 +145,20 @@ public final class InputLogic { */ public void startInput(final String combiningSpec, final SettingsValues settingsValues) { mEnteredText = null; + if (!mWordComposer.getTypedWord().isEmpty()) { + // For messaging apps that offer send button, the IME does not get the opportunity + // to capture the last word. This block should capture those uncommitted words. + // The timestamp at which it is captured is not accurate but close enough. + StatsUtils.onWordCommitUserTyped( + mWordComposer.getTypedWord(), mWordComposer.isBatchMode()); + } mWordComposer.restartCombining(combiningSpec); resetComposingState(true /* alsoResetLastComposedWord */); mDeleteCount = 0; mSpaceState = SpaceState.NONE; mRecapitalizeStatus.disable(); // Do not perform recapitalize until the cursor is moved once mCurrentlyPressedHardwareKeys.clear(); - mSuggestedWords = SuggestedWords.EMPTY; + mSuggestedWords = SuggestedWords.getEmptyInstance(); // In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying // so we try using some heuristics to find out about these and fix them. mConnection.tryFixLyingCursorPosition(); @@ -325,7 +332,7 @@ public final class InputLogic { // however need to reset the suggestion strip right away, because we know we can't take // the risk of calling commitCompletion twice because we don't know how the app will react. if (suggestionInfo.isKindOf(SuggestedWordInfo.KIND_APP_DEFINED)) { - mSuggestedWords = SuggestedWords.EMPTY; + mSuggestedWords = SuggestedWords.getEmptyInstance(); mSuggestionStripViewAccessor.setNeutralSuggestionStrip(); inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); resetComposingState(true /* alsoResetLastComposedWord */); @@ -501,7 +508,7 @@ public final class InputLogic { final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { mInputLogicHandler.onStartBatchInput(); handler.showGesturePreviewAndSuggestionStrip( - SuggestedWords.EMPTY, false /* dismissGestureFloatingPreviewText */); + SuggestedWords.getEmptyInstance(), false /* dismissGestureFloatingPreviewText */); handler.cancelUpdateSuggestionStrip(); ++mAutoCommitSequenceNumber; mConnection.beginBatchEdit(); @@ -600,14 +607,14 @@ public final class InputLogic { public void onCancelBatchInput(final LatinIME.UIHandler handler) { mInputLogicHandler.onCancelBatchInput(); handler.showGesturePreviewAndSuggestionStrip( - SuggestedWords.EMPTY, true /* dismissGestureFloatingPreviewText */); + SuggestedWords.getEmptyInstance(), true /* dismissGestureFloatingPreviewText */); } // TODO: on the long term, this method should become private, but it will be difficult. // Especially, how do we deal with InputMethodService.onDisplayCompletions? public void setSuggestedWords(final SuggestedWords suggestedWords, final SettingsValues settingsValues, final LatinIME.UIHandler handler) { - if (SuggestedWords.EMPTY != suggestedWords) { + if (!suggestedWords.isEmpty()) { final String autoCorrection; final String dictType; if (suggestedWords.mWillAutoCorrect) { @@ -1393,7 +1400,7 @@ public final class InputLogic { + "requested!"); } // Clear the suggestions strip. - mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.EMPTY); + mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.getEmptyInstance()); return; } @@ -1885,9 +1892,8 @@ public final class InputLogic { */ private SuggestedWords retrieveOlderSuggestions(final String typedWord, final SuggestedWords previousSuggestedWords) { - final SuggestedWords oldSuggestedWords = - previousSuggestedWords.isPunctuationSuggestions() ? SuggestedWords.EMPTY - : previousSuggestedWords; + final SuggestedWords oldSuggestedWords = previousSuggestedWords.isPunctuationSuggestions() + ? SuggestedWords.getEmptyInstance() : previousSuggestedWords; final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords); return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */, diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index 34d4d4ed7..d1486f630 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -35,6 +35,7 @@ import java.util.Locale; */ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName(); + private final static int SUPPORTED_NGRAM = 2; // TODO: 3 // TODO: Make this constructor private /* package */ UserHistoryDictionary(final Context context, final Locale locale) { @@ -61,9 +62,7 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary, final PrevWordsInfo prevWordsInfo, final String word, final boolean isValid, final int timestamp, final DistracterFilter distracterFilter) { - final CharSequence prevWord = prevWordsInfo.mPrevWordsInfo[0].mWord; - if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH || - (prevWord != null && prevWord.length() > Constants.DICTIONARY_MAX_WORD_LENGTH)) { + if (word.length() > Constants.DICTIONARY_MAX_WORD_LENGTH) { return; } final int frequency = isValid ? @@ -71,17 +70,29 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas userHistoryDictionary.addUnigramEntryWithCheckingDistracter(word, frequency, null /* shortcutTarget */, 0 /* shortcutFreq */, false /* isNotAWord */, false /* isBlacklisted */, timestamp, distracterFilter); - // Do not insert a word as a bigram of itself - if (TextUtils.equals(word, prevWord)) { - return; - } - if (null != prevWord) { - if (prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence) { - // Beginning-of-Sentence n-gram entry is treated as a n-gram entry of invalid word. - userHistoryDictionary.addNgramEntry(prevWordsInfo, word, + + final boolean isBeginningOfSentenceContext = + prevWordsInfo.mPrevWordsInfo[0].mIsBeginningOfSentence; + final PrevWordsInfo prevWordsInfoToBeSaved = + prevWordsInfo.getTrimmedPrevWordsInfo(SUPPORTED_NGRAM - 1); + for (int i = 0; i < prevWordsInfoToBeSaved.getPrevWordCount(); i++) { + final CharSequence prevWord = prevWordsInfoToBeSaved.mPrevWordsInfo[i].mWord; + if (prevWord == null || (prevWord.length() > Constants.DICTIONARY_MAX_WORD_LENGTH)) { + return; + } + // Do not insert a word as a bigram of itself + if (i == 0 && TextUtils.equals(word, prevWord)) { + return; + } + if (isBeginningOfSentenceContext) { + // Beginning-of-Sentence n-gram entry is added as an n-gram entry of an OOV word. + userHistoryDictionary.addNgramEntry( + prevWordsInfoToBeSaved.getTrimmedPrevWordsInfo(i + 1), word, FREQUENCY_FOR_WORDS_NOT_IN_DICTS, timestamp); } else { - userHistoryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp); + userHistoryDictionary.addNgramEntry( + prevWordsInfoToBeSaved.getTrimmedPrevWordsInfo(i + 1), word, frequency, + timestamp); } } } diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java index 06ab1e2d2..ffb0ad7bf 100644 --- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java @@ -30,8 +30,8 @@ import android.widget.Toast; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SubtypeSwitcher; +import com.android.inputmethod.latin.accounts.LoginAccountUtils; import com.android.inputmethod.latin.define.ProductionFlags; -import com.android.inputmethod.latin.utils.LoginAccountUtils; import javax.annotation.Nullable; diff --git a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java index a6cb55db1..3303ab093 100644 --- a/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/AdvancedSettingsFragment.java @@ -109,6 +109,8 @@ public final class AdvancedSettingsFragment extends SubScreenFragment { removePreference(Settings.PREF_ENABLE_METRICS_LOGGING); } + AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this); + setupKeypressVibrationDurationSettings(); setupKeypressSoundVolumeSettings(); refreshEnablingsOfKeypressSoundAndVibrationSettings(); diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index 3339ab57f..99f761ca6 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -64,6 +64,7 @@ public class SettingsValues { public final boolean mSoundOn; public final boolean mKeyPreviewPopupOn; public final boolean mShowsVoiceInputKey; + public final String mAccountName; public final boolean mIncludesOtherImesInLanguageSwitchList; public final boolean mShowsLanguageSwitchKey; public final boolean mUseContactsDict; @@ -140,6 +141,7 @@ public class SettingsValues { mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res) && mInputAttributes.mShouldShowVoiceInputKey && SubtypeSwitcher.getInstance().isShortcutImeEnabled(); + mAccountName = prefs.getString(Settings.PREF_ACCOUNT_NAME, null); final String autoCorrectionThresholdRawValue = prefs.getString( Settings.PREF_AUTO_CORRECTION_THRESHOLD, res.getString(R.string.auto_correction_threshold_mode_index_modest)); @@ -178,7 +180,7 @@ public class SettingsValues { mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect; mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs); - AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray( + AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray(context, prefs, mAdditionalFeaturesSettingValues); mTextHighlightColorForAddToDictionaryIndicator = res.getColor( R.color.text_decorator_add_to_dictionary_indicator_text_highlight_color); @@ -383,6 +385,8 @@ public class SettingsValues { sb.append("" + mKeyPreviewPopupOn); sb.append("\n mShowsVoiceInputKey = "); sb.append("" + mShowsVoiceInputKey); + sb.append("\n mAccountName = "); + sb.append("" + mAccountName); sb.append("\n mIncludesOtherImesInLanguageSwitchList = "); sb.append("" + mIncludesOtherImesInLanguageSwitchList); sb.append("\n mShowsLanguageSwitchKey = "); diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index f7b6f919d..907e3fa42 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -40,6 +40,8 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView { public abstract void onSuggestionSelected(final SuggestedWordInfo info); } + private boolean mIsInModalMode; + public MoreSuggestionsView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.moreKeysKeyboardViewStyle); } @@ -53,6 +55,7 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView { @Override public void setKeyboard(final Keyboard keyboard) { super.setKeyboard(keyboard); + mIsInModalMode = false; // With accessibility mode off, {@link #mAccessibilityDelegate} is set to null at the // above {@link MoreKeysKeyboardView#setKeyboard(Keyboard)} call. // With accessibility mode on, {@link #mAccessibilityDelegate} is set to a @@ -74,12 +77,17 @@ public final class MoreSuggestionsView extends MoreKeysKeyboardView { updateKeyDrawParams(keyHeight); } - public void adjustVerticalCorrectionForModalMode() { + public void setModalMode() { + mIsInModalMode = true; // Set vertical correction to zero (Reset more keys keyboard sliding allowance // {@link R#dimen.config_more_keys_keyboard_slide_allowance}). mKeyDetector.setKeyboard(getKeyboard(), -getPaddingLeft(), -getPaddingTop()); } + public boolean isInModalMode() { + return mIsInModalMode; + } + @Override protected void onKeyInput(final Key key, final int x, final int y) { if (!(key instanceof MoreSuggestionKey)) { diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 33745a846..43f6175ca 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -82,7 +82,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick private final ArrayList<View> mDividerViews = new ArrayList<>(); Listener mListener; - private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; + private SuggestedWords mSuggestedWords = SuggestedWords.getEmptyInstance(); private int mStartIndexOfMoreSuggestions; private final SuggestionStripLayoutHelper mLayoutHelper; @@ -131,6 +131,10 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mImportantNoticeStrip.setVisibility(VISIBLE); } + public boolean isShowingImportantNoticeStrip() { + return mImportantNoticeStrip.getVisibility() == VISIBLE; + } + public boolean isShowingAddToDictionaryStrip() { return mAddToDictionaryStrip.getVisibility() == VISIBLE; } @@ -393,11 +397,17 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick @Override public boolean onInterceptTouchEvent(final MotionEvent me) { + if (mStripVisibilityGroup.isShowingImportantNoticeStrip()) { + return false; + } if (!mMoreSuggestionsView.isShowingInParent()) { mLastX = (int)me.getX(); mLastY = (int)me.getY(); return mMoreSuggestionsSlidingDetector.onTouchEvent(me); } + if (mMoreSuggestionsView.isInModalMode()) { + return false; + } final int action = me.getAction(); final int index = me.getActionIndex(); @@ -416,7 +426,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) { // Decided to be in the modal input mode. - mMoreSuggestionsView.adjustVerticalCorrectionForModalMode(); + mMoreSuggestionsView.setModalMode(); } return false; } diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java index 8b7077879..ea406fa75 100644 --- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java @@ -23,15 +23,24 @@ import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.R; +import java.util.concurrent.TimeUnit; + public final class ImportantNoticeUtils { private static final String TAG = ImportantNoticeUtils.class.getSimpleName(); // {@link SharedPreferences} name to save the last important notice version that has been // displayed to users. private static final String PREFERENCE_NAME = "important_notice_pref"; - private static final String KEY_IMPORTANT_NOTICE_VERSION = "important_notice_version"; + @UsedForTesting + static final String KEY_IMPORTANT_NOTICE_VERSION = "important_notice_version"; + @UsedForTesting + static final String KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE = + "timestamp_of_first_important_notice"; + @UsedForTesting + static final long TIMEOUT_OF_IMPORTANT_NOTICE = TimeUnit.HOURS.toMillis(23); public static final int VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS = 1; // Copy of the hidden {@link Settings.Secure#USER_SETUP_COMPLETE} settings key. @@ -56,15 +65,18 @@ public final class ImportantNoticeUtils { } } - private static SharedPreferences getImportantNoticePreferences(final Context context) { + @UsedForTesting + static SharedPreferences getImportantNoticePreferences(final Context context) { return context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE); } - private static int getCurrentImportantNoticeVersion(final Context context) { + @UsedForTesting + static int getCurrentImportantNoticeVersion(final Context context) { return context.getResources().getInteger(R.integer.config_important_notice_version); } - private static int getLastImportantNoticeVersion(final Context context) { + @UsedForTesting + static int getLastImportantNoticeVersion(final Context context) { return getImportantNoticePreferences(context).getInt(KEY_IMPORTANT_NOTICE_VERSION, 0); } @@ -77,6 +89,20 @@ public final class ImportantNoticeUtils { return getCurrentImportantNoticeVersion(context) > lastVersion; } + @UsedForTesting + static boolean hasTimeoutPassed(final Context context, final long currentTimeInMillis) { + final SharedPreferences prefs = getImportantNoticePreferences(context); + if (!prefs.contains(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE)) { + prefs.edit() + .putLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis) + .apply(); + } + final long firstDisplayTimeInMillis = prefs.getLong( + KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis); + final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis; + return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE; + } + public static boolean shouldShowImportantNotice(final Context context) { if (!hasNewImportantNotice(context)) { return false; @@ -88,6 +114,10 @@ public final class ImportantNoticeUtils { if (isInSystemSetupWizard(context)) { return false; } + if (hasTimeoutPassed(context, System.currentTimeMillis())) { + updateLastImportantNoticeVersion(context); + return false; + } return true; } @@ -95,11 +125,12 @@ public final class ImportantNoticeUtils { getImportantNoticePreferences(context) .edit() .putInt(KEY_IMPORTANT_NOTICE_VERSION, getNextImportantNoticeVersion(context)) + .remove(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE) .apply(); } public static String getNextImportantNoticeTitle(final Context context) { - final int nextVersion = getCurrentImportantNoticeVersion(context); + final int nextVersion = getNextImportantNoticeVersion(context); final String[] importantNoticeTitleArray = context.getResources().getStringArray( R.array.important_notice_title_array); if (nextVersion > 0 && nextVersion < importantNoticeTitleArray.length) { |