aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java6
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java117
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/DownloadManagerWrapper.java10
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java58
-rw-r--r--java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java17
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java23
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java74
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java288
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java191
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java18
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java13
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java10
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java17
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java2
14 files changed, 475 insertions, 369 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index 1d9b9991e..80def701d 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -350,7 +350,8 @@ public final class DictionaryProvider extends ContentProvider {
clientId);
if (null == results) {
return Collections.<WordListInfo>emptyList();
- } else {
+ }
+ try {
final HashMap<String, WordListInfo> dicts = new HashMap<String, WordListInfo>();
final int idIndex = results.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
final int localeIndex = results.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
@@ -416,8 +417,9 @@ public final class DictionaryProvider extends ContentProvider {
}
} while (results.moveToNext());
}
- results.close();
return Collections.unmodifiableCollection(dicts.values());
+ } finally {
+ results.close();
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
index d18639741..dae2f22a4 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java
@@ -283,63 +283,70 @@ public final class DictionarySettingsFragment extends PreferenceFragment
final ArrayList<Preference> result = new ArrayList<Preference>();
result.add(createErrorMessage(activity, R.string.cannot_connect_to_dict_service));
return result;
- } else if (!cursor.moveToFirst()) {
- final ArrayList<Preference> result = new ArrayList<Preference>();
- result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
- cursor.close();
- return result;
- } else {
- final String systemLocaleString = Locale.getDefault().toString();
- final TreeMap<String, WordListPreference> prefMap =
- new TreeMap<String, WordListPreference>();
- final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
- final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
- final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
- final int descriptionIndex = cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
- final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
- final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
- do {
- final String wordlistId = cursor.getString(idIndex);
- final int version = cursor.getInt(versionIndex);
- final String localeString = cursor.getString(localeIndex);
- final Locale locale = new Locale(localeString);
- final String description = cursor.getString(descriptionIndex);
- final int status = cursor.getInt(statusIndex);
- final int matchLevel = LocaleUtils.getMatchLevel(systemLocaleString, localeString);
- final String matchLevelString = LocaleUtils.getMatchLevelSortedString(matchLevel);
- final int filesize = cursor.getInt(filesizeIndex);
- // The key is sorted in lexicographic order, according to the match level, then
- // the description.
- final String key = matchLevelString + "." + description + "." + wordlistId;
- final WordListPreference existingPref = prefMap.get(key);
- if (null == existingPref || existingPref.hasPriorityOver(status)) {
- final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
- final WordListPreference pref;
- if (null != oldPreference
- && oldPreference.mVersion == version
- && oldPreference.hasStatus(status)
- && oldPreference.mLocale.equals(locale)) {
- // If the old preference has all the new attributes, reuse it. Ideally, we
- // should reuse the old pref even if its status is different and call
- // setStatus here, but setStatus calls Preference#setSummary() which needs
- // to be done on the UI thread and we're not on the UI thread here. We
- // could do all this work on the UI thread, but in this case it's probably
- // lighter to stay on a background thread and throw this old preference out.
- pref = oldPreference;
- } else {
- // Otherwise, discard it and create a new one instead.
- // TODO: when the status is different from the old one, we need to
- // animate the old one out before animating the new one in.
- pref = new WordListPreference(activity, mDictionaryListInterfaceState,
- mClientId, wordlistId, version, locale, description, status,
- filesize);
+ }
+ try {
+ if (!cursor.moveToFirst()) {
+ final ArrayList<Preference> result = new ArrayList<Preference>();
+ result.add(createErrorMessage(activity, R.string.no_dictionaries_available));
+ return result;
+ } else {
+ final String systemLocaleString = Locale.getDefault().toString();
+ final TreeMap<String, WordListPreference> prefMap =
+ new TreeMap<String, WordListPreference>();
+ final int idIndex = cursor.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
+ final int versionIndex = cursor.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
+ final int localeIndex = cursor.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
+ final int descriptionIndex =
+ cursor.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN);
+ final int statusIndex = cursor.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
+ final int filesizeIndex = cursor.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN);
+ do {
+ final String wordlistId = cursor.getString(idIndex);
+ final int version = cursor.getInt(versionIndex);
+ final String localeString = cursor.getString(localeIndex);
+ final Locale locale = new Locale(localeString);
+ final String description = cursor.getString(descriptionIndex);
+ final int status = cursor.getInt(statusIndex);
+ final int matchLevel =
+ LocaleUtils.getMatchLevel(systemLocaleString, localeString);
+ final String matchLevelString =
+ LocaleUtils.getMatchLevelSortedString(matchLevel);
+ final int filesize = cursor.getInt(filesizeIndex);
+ // The key is sorted in lexicographic order, according to the match level, then
+ // the description.
+ final String key = matchLevelString + "." + description + "." + wordlistId;
+ final WordListPreference existingPref = prefMap.get(key);
+ if (null == existingPref || existingPref.hasPriorityOver(status)) {
+ final WordListPreference oldPreference = mCurrentPreferenceMap.get(key);
+ final WordListPreference pref;
+ if (null != oldPreference
+ && oldPreference.mVersion == version
+ && oldPreference.hasStatus(status)
+ && oldPreference.mLocale.equals(locale)) {
+ // If the old preference has all the new attributes, reuse it. Ideally,
+ // we should reuse the old pref even if its status is different and call
+ // setStatus here, but setStatus calls Preference#setSummary() which
+ // needs to be done on the UI thread and we're not on the UI thread
+ // here. We could do all this work on the UI thread, but in this case
+ // it's probably lighter to stay on a background thread and throw this
+ // old preference out.
+ pref = oldPreference;
+ } else {
+ // Otherwise, discard it and create a new one instead.
+ // TODO: when the status is different from the old one, we need to
+ // animate the old one out before animating the new one in.
+ pref = new WordListPreference(activity, mDictionaryListInterfaceState,
+ mClientId, wordlistId, version, locale, description, status,
+ filesize);
+ }
+ prefMap.put(key, pref);
}
- prefMap.put(key, pref);
- }
- } while (cursor.moveToNext());
+ } while (cursor.moveToNext());
+ mCurrentPreferenceMap = prefMap;
+ return prefMap.values();
+ }
+ } finally {
cursor.close();
- mCurrentPreferenceMap = prefMap;
- return prefMap.values();
}
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/DownloadManagerWrapper.java b/java/src/com/android/inputmethod/dictionarypack/DownloadManagerWrapper.java
index e95ca1799..75cc7d4cb 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DownloadManagerWrapper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DownloadManagerWrapper.java
@@ -59,6 +59,10 @@ public class DownloadManagerWrapper {
// be opened. It may be a problem with file system corruption. In any case, there is
// not much we can do apart from avoiding crashing.
Log.e(TAG, "Can't remove files with ID " + ids + " from download manager", e);
+ } catch (IllegalArgumentException e) {
+ // Not sure how this can happen, but it could be another case where the provider
+ // is disabled. Or it could be a bug in older versions of the framework.
+ Log.e(TAG, "Can't find the content URL for DownloadManager?", e);
}
}
@@ -69,6 +73,8 @@ public class DownloadManagerWrapper {
}
} catch (SQLiteException e) {
Log.e(TAG, "Can't open downloaded file with ID " + fileId, e);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Can't find the content URL for DownloadManager?", e);
}
// We come here if mDownloadManager is null or if an exception was thrown.
throw new FileNotFoundException();
@@ -81,6 +87,8 @@ public class DownloadManagerWrapper {
}
} catch (SQLiteException e) {
Log.e(TAG, "Can't query the download manager", e);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Can't find the content URL for DownloadManager?", e);
}
// We come here if mDownloadManager is null or if an exception was thrown.
return null;
@@ -93,6 +101,8 @@ public class DownloadManagerWrapper {
}
} catch (SQLiteException e) {
Log.e(TAG, "Can't enqueue a request with the download manager", e);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Can't find the content URL for DownloadManager?", e);
}
return 0;
}
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index ff5aba6d8..8badaf4b9 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -533,12 +533,17 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
PENDINGID_COLUMN + "= ?",
new String[] { Long.toString(id) },
null, null, null);
- // There should never be more than one result. If because of some bug there are, returning
- // only one result is the right thing to do, because we couldn't handle several anyway
- // and we should still handle one.
- final ContentValues result = getFirstLineAsContentValues(cursor);
- cursor.close();
- return result;
+ if (null == cursor) {
+ return null;
+ }
+ try {
+ // There should never be more than one result. If because of some bug there are,
+ // returning only one result is the right thing to do, because we couldn't handle
+ // several anyway and we should still handle one.
+ return getFirstLineAsContentValues(cursor);
+ } finally {
+ cursor.close();
+ }
}
/**
@@ -559,11 +564,16 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
new String[] { id, Integer.toString(STATUS_INSTALLED),
Integer.toString(STATUS_DELETING) },
null, null, null);
- // There should only be one result, but if there are several, we can't tell which
- // is the best, so we just return the first one.
- final ContentValues result = getFirstLineAsContentValues(cursor);
- cursor.close();
- return result;
+ if (null == cursor) {
+ return null;
+ }
+ try {
+ // There should only be one result, but if there are several, we can't tell which
+ // is the best, so we just return the first one.
+ return getFirstLineAsContentValues(cursor);
+ } finally {
+ cursor.close();
+ }
}
/**
@@ -622,10 +632,15 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
METADATA_TABLE_COLUMNS,
WORDLISTID_COLUMN + "= ? AND " + VERSION_COLUMN + "= ?",
new String[] { id, Integer.toString(version) }, null, null, null);
- // This is a lookup by primary key, so there can't be more than one result.
- final ContentValues result = getFirstLineAsContentValues(cursor);
- cursor.close();
- return result;
+ if (null == cursor) {
+ return null;
+ }
+ try {
+ // This is a lookup by primary key, so there can't be more than one result.
+ return getFirstLineAsContentValues(cursor);
+ } finally {
+ cursor.close();
+ }
}
/**
@@ -641,10 +656,15 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
METADATA_TABLE_COLUMNS,
WORDLISTID_COLUMN + "= ?",
new String[] { id }, null, null, VERSION_COLUMN + " DESC", "1");
- // This is a lookup by primary key, so there can't be more than one result.
- final ContentValues result = getFirstLineAsContentValues(cursor);
- cursor.close();
- return result;
+ if (null == cursor) {
+ return null;
+ }
+ try {
+ // This is a lookup by primary key, so there can't be more than one result.
+ return getFirstLineAsContentValues(cursor);
+ } finally {
+ cursor.close();
+ }
}
/**
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
index a0147b6d6..5c2289911 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataHandler.java
@@ -44,8 +44,7 @@ public class MetadataHandler {
*/
private static List<WordListMetadata> makeMetadataObject(final Cursor results) {
final ArrayList<WordListMetadata> buildingMetadata = new ArrayList<WordListMetadata>();
-
- if (results.moveToFirst()) {
+ if (null != results && results.moveToFirst()) {
final int localeColumn = results.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
final int typeColumn = results.getColumnIndex(MetadataDbHelper.TYPE_COLUMN);
final int descriptionColumn =
@@ -61,7 +60,6 @@ public class MetadataHandler {
final int versionIndex = results.getColumnIndex(MetadataDbHelper.VERSION_COLUMN);
final int formatVersionIndex =
results.getColumnIndex(MetadataDbHelper.FORMATVERSION_COLUMN);
-
do {
buildingMetadata.add(new WordListMetadata(results.getString(idIndex),
results.getInt(typeColumn),
@@ -75,8 +73,6 @@ public class MetadataHandler {
results.getInt(formatVersionIndex),
0, results.getString(localeColumn)));
} while (results.moveToNext());
-
- results.close();
}
return Collections.unmodifiableList(buildingMetadata);
}
@@ -92,9 +88,14 @@ public class MetadataHandler {
// If clientId is null, we get a cursor on the default database (see
// MetadataDbHelper#getInstance() for more on this)
final Cursor results = MetadataDbHelper.queryCurrentMetadata(context, clientId);
- final List<WordListMetadata> resultList = makeMetadataObject(results);
- results.close();
- return resultList;
+ // If null, we should return makeMetadataObject(null), so we go through.
+ try {
+ return makeMetadataObject(results);
+ } finally {
+ if (null != results) {
+ results.close();
+ }
+ }
}
/**
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index b4382bc2c..e428b1d54 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -142,7 +142,7 @@ public final class BinaryDictionaryFileDumper {
final ContentProviderClient client = context.getContentResolver().
acquireContentProviderClient(getProviderUriBuilder("").build());
if (null == client) return Collections.<WordListInfo>emptyList();
-
+ Cursor cursor = null;
try {
final Uri.Builder builder = getContentUriBuilderForType(clientId, client,
QUERY_PATH_DICT_INFO, locale.toString());
@@ -154,24 +154,22 @@ public final class BinaryDictionaryFileDumper {
final boolean isProtocolV2 = (QUERY_PARAMETER_PROTOCOL_VALUE.equals(
queryUri.getQueryParameter(QUERY_PARAMETER_PROTOCOL)));
- Cursor c = client.query(queryUri, DICTIONARY_PROJECTION, null, null, null);
- if (isProtocolV2 && null == c) {
+ cursor = client.query(queryUri, DICTIONARY_PROJECTION, null, null, null);
+ if (isProtocolV2 && null == cursor) {
reinitializeClientRecordInDictionaryContentProvider(context, client, clientId);
- c = client.query(queryUri, DICTIONARY_PROJECTION, null, null, null);
+ cursor = client.query(queryUri, DICTIONARY_PROJECTION, null, null, null);
}
- if (null == c) return Collections.<WordListInfo>emptyList();
- if (c.getCount() <= 0 || !c.moveToFirst()) {
- c.close();
+ if (null == cursor) return Collections.<WordListInfo>emptyList();
+ if (cursor.getCount() <= 0 || !cursor.moveToFirst()) {
return Collections.<WordListInfo>emptyList();
}
final ArrayList<WordListInfo> list = CollectionUtils.newArrayList();
do {
- final String wordListId = c.getString(0);
- final String wordListLocale = c.getString(1);
+ final String wordListId = cursor.getString(0);
+ final String wordListLocale = cursor.getString(1);
if (TextUtils.isEmpty(wordListId)) continue;
list.add(new WordListInfo(wordListId, wordListLocale));
- } while (c.moveToNext());
- c.close();
+ } while (cursor.moveToNext());
return list;
} catch (RemoteException e) {
// The documentation is unclear as to in which cases this may happen, but it probably
@@ -186,6 +184,9 @@ public final class BinaryDictionaryFileDumper {
Log.e(TAG, "Unexpected exception communicating with the dictionary pack", e);
return Collections.<WordListInfo>emptyList();
} finally {
+ if (null != cursor) {
+ cursor.close();
+ }
client.release();
}
}
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index d626ff926..11a9d1fe4 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -139,23 +139,24 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
}
private void loadDictionaryAsyncForUri(final Uri uri) {
+ Cursor cursor = null;
try {
- Cursor cursor = mContext.getContentResolver()
- .query(uri, PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- sContactCountAtLastRebuild = getContactCount();
- addWords(cursor);
- }
- } finally {
- cursor.close();
- }
+ cursor = mContext.getContentResolver().query(uri, PROJECTION, null, null, null);
+ if (null == cursor) {
+ return;
+ }
+ if (cursor.moveToFirst()) {
+ sContactCountAtLastRebuild = getContactCount();
+ addWords(cursor);
}
} catch (final SQLiteException e) {
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
} catch (final IllegalStateException e) {
Log.e(TAG, "Contacts DB is having problems", e);
+ } finally {
+ if (null != cursor) {
+ cursor.close();
+ }
}
}
@@ -186,18 +187,20 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
private int getContactCount() {
// TODO: consider switching to a rawQuery("select count(*)...") on the database if
// performance is a bottleneck.
+ Cursor cursor = null;
try {
- final Cursor cursor = mContext.getContentResolver().query(
- Contacts.CONTENT_URI, PROJECTION_ID_ONLY, null, null, null);
- if (cursor != null) {
- try {
- return cursor.getCount();
- } finally {
- cursor.close();
- }
+ cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION_ID_ONLY,
+ null, null, null);
+ if (null == cursor) {
+ return 0;
}
+ return cursor.getCount();
} catch (final SQLiteException e) {
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
+ } finally {
+ if (null != cursor) {
+ cursor.close();
+ }
}
return 0;
}
@@ -281,26 +284,27 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
// Check all contacts since it's not possible to find out which names have changed.
// This is needed because it's possible to receive extraneous onChange events even when no
// name has changed.
- Cursor cursor = mContext.getContentResolver().query(
- Contacts.CONTENT_URI, PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- if (cursor.moveToFirst()) {
- while (!cursor.isAfterLast()) {
- String name = cursor.getString(INDEX_NAME);
- if (isValidName(name) && !isNameInDictionary(name)) {
- if (DEBUG) {
- Log.d(TAG, "Contact name missing: " + name + " (runtime = "
- + (SystemClock.uptimeMillis() - startTime) + " ms)");
- }
- return true;
+ final Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI, PROJECTION,
+ null, null, null);
+ if (null == cursor) {
+ return false;
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ while (!cursor.isAfterLast()) {
+ String name = cursor.getString(INDEX_NAME);
+ if (isValidName(name) && !isNameInDictionary(name)) {
+ if (DEBUG) {
+ Log.d(TAG, "Contact name missing: " + name + " (runtime = "
+ + (SystemClock.uptimeMillis() - startTime) + " ms)");
}
- cursor.moveToNext();
+ return true;
}
+ cursor.moveToNext();
}
- } finally {
- cursor.close();
}
+ } finally {
+ cursor.close();
}
if (DEBUG) {
Log.d(TAG, "No contacts changed. (runtime = " + (SystemClock.uptimeMillis() - startTime)
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index 01c17f2f2..726b3d141 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -20,9 +20,13 @@ import android.text.InputType;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.InputTypeUtils;
import com.android.inputmethod.latin.utils.StringUtils;
+import java.util.ArrayList;
+import java.util.Arrays;
+
/**
* Class to hold attributes of the input field.
*/
@@ -62,49 +66,43 @@ public final class InputAttributes {
mInputTypeNoAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
mShouldInsertSpacesAutomatically = false;
- } else {
- final int variation = inputType & InputType.TYPE_MASK_VARIATION;
- final boolean flagNoSuggestions =
- 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
- final boolean flagMultiLine =
- 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE);
- final boolean flagAutoCorrect =
- 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
- final boolean flagAutoComplete =
- 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
-
- mIsPasswordField = InputTypeUtils.isPasswordInputType(inputType)
- || InputTypeUtils.isVisiblePasswordInputType(inputType);
- // TODO: Have a helper method in InputTypeUtils
- // Make sure that passwords are not displayed in {@link SuggestionStripView}.
- if (mIsPasswordField
- || InputTypeUtils.isEmailVariation(variation)
- || InputType.TYPE_TEXT_VARIATION_URI == variation
- || InputType.TYPE_TEXT_VARIATION_FILTER == variation
- || flagNoSuggestions
- || flagAutoComplete) {
- mIsSettingsSuggestionStripOn = false;
- } else {
- mIsSettingsSuggestionStripOn = true;
- }
+ return;
+ }
+ // inputClass == InputType.TYPE_CLASS_TEXT
+ final int variation = inputType & InputType.TYPE_MASK_VARIATION;
+ final boolean flagNoSuggestions =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ final boolean flagMultiLine =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE);
+ final boolean flagAutoCorrect =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT);
+ final boolean flagAutoComplete =
+ 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
- mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
-
- // If it's a browser edit field and auto correct is not ON explicitly, then
- // disable auto correction, but keep suggestions on.
- // If NO_SUGGESTIONS is set, don't do prediction.
- // If it's not multiline and the autoCorrect flag is not set, then don't correct
- if ((variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
- && !flagAutoCorrect)
- || flagNoSuggestions
- || (!flagAutoCorrect && !flagMultiLine)) {
- mInputTypeNoAutoCorrect = true;
- } else {
- mInputTypeNoAutoCorrect = false;
- }
+ mIsPasswordField = InputTypeUtils.isPasswordInputType(inputType)
+ || InputTypeUtils.isVisiblePasswordInputType(inputType);
+ // TODO: Have a helper method in InputTypeUtils
+ // Make sure that passwords are not displayed in {@link SuggestionStripView}.
+ final boolean noSuggestionStrip = mIsPasswordField
+ || InputTypeUtils.isEmailVariation(variation)
+ || InputType.TYPE_TEXT_VARIATION_URI == variation
+ || InputType.TYPE_TEXT_VARIATION_FILTER == variation
+ || flagNoSuggestions
+ || flagAutoComplete;
+ mIsSettingsSuggestionStripOn = !noSuggestionStrip;
- mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
- }
+ mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
+
+ // If it's a browser edit field and auto correct is not ON explicitly, then
+ // disable auto correction, but keep suggestions on.
+ // If NO_SUGGESTIONS is set, don't do prediction.
+ // If it's not multiline and the autoCorrect flag is not set, then don't correct
+ mInputTypeNoAutoCorrect =
+ (variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT && !flagAutoCorrect)
+ || flagNoSuggestions
+ || (!flagAutoCorrect && !flagMultiLine);
+
+ mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
}
public boolean isTypeNull() {
@@ -117,96 +115,142 @@ public final class InputAttributes {
@SuppressWarnings("unused")
private void dumpFlags(final int inputType) {
- Log.i(TAG, "Input class:");
final int inputClass = inputType & InputType.TYPE_MASK_CLASS;
- if (inputClass == InputType.TYPE_CLASS_TEXT)
- Log.i(TAG, " TYPE_CLASS_TEXT");
- if (inputClass == InputType.TYPE_CLASS_PHONE)
- Log.i(TAG, " TYPE_CLASS_PHONE");
- if (inputClass == InputType.TYPE_CLASS_NUMBER)
- Log.i(TAG, " TYPE_CLASS_NUMBER");
- if (inputClass == InputType.TYPE_CLASS_DATETIME)
- Log.i(TAG, " TYPE_CLASS_DATETIME");
- Log.i(TAG, "Variation:");
- switch (InputType.TYPE_MASK_VARIATION & inputType) {
- case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
- Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_ADDRESS");
- break;
- case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
- Log.i(TAG, " TYPE_TEXT_VARIATION_EMAIL_SUBJECT");
- break;
- case InputType.TYPE_TEXT_VARIATION_FILTER:
- Log.i(TAG, " TYPE_TEXT_VARIATION_FILTER");
- break;
- case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE:
- Log.i(TAG, " TYPE_TEXT_VARIATION_LONG_MESSAGE");
- break;
- case InputType.TYPE_TEXT_VARIATION_NORMAL:
- Log.i(TAG, " TYPE_TEXT_VARIATION_NORMAL");
- break;
- case InputType.TYPE_TEXT_VARIATION_PASSWORD:
- Log.i(TAG, " TYPE_TEXT_VARIATION_PASSWORD");
- break;
- case InputType.TYPE_TEXT_VARIATION_PERSON_NAME:
- Log.i(TAG, " TYPE_TEXT_VARIATION_PERSON_NAME");
- break;
- case InputType.TYPE_TEXT_VARIATION_PHONETIC:
- Log.i(TAG, " TYPE_TEXT_VARIATION_PHONETIC");
- break;
- case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
- Log.i(TAG, " TYPE_TEXT_VARIATION_POSTAL_ADDRESS");
- break;
- case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE:
- Log.i(TAG, " TYPE_TEXT_VARIATION_SHORT_MESSAGE");
- break;
- case InputType.TYPE_TEXT_VARIATION_URI:
- Log.i(TAG, " TYPE_TEXT_VARIATION_URI");
- break;
- case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
- Log.i(TAG, " TYPE_TEXT_VARIATION_VISIBLE_PASSWORD");
- break;
- case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT:
- Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EDIT_TEXT");
- break;
- case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
- Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS");
- break;
- case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD:
- Log.i(TAG, " TYPE_TEXT_VARIATION_WEB_PASSWORD");
- break;
- default:
- Log.i(TAG, " Unknown variation");
- break;
+ final String inputClassString = toInputClassString(inputClass);
+ final String variationString = toVariationString(
+ inputClass, inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ final String flagsString = toFlagsString(inputType & InputType.TYPE_MASK_FLAGS);
+ Log.i(TAG, "Input class: " + inputClassString);
+ Log.i(TAG, "Variation: " + variationString);
+ Log.i(TAG, "Flags: " + flagsString);
+ }
+
+ private static String toInputClassString(final int inputClass) {
+ switch (inputClass) {
+ case InputType.TYPE_CLASS_TEXT:
+ return "TYPE_CLASS_TEXT";
+ case InputType.TYPE_CLASS_PHONE:
+ return "TYPE_CLASS_PHONE";
+ case InputType.TYPE_CLASS_NUMBER:
+ return "TYPE_CLASS_NUMBER";
+ case InputType.TYPE_CLASS_DATETIME:
+ return "TYPE_CLASS_DATETIME";
+ default:
+ return String.format("unknownInputClass<0x%08x>", inputClass);
+ }
+ }
+
+ private static String toVariationString(final int inputClass, final int variation) {
+ switch (inputClass) {
+ case InputType.TYPE_CLASS_TEXT:
+ return toTextVariationString(variation);
+ case InputType.TYPE_CLASS_NUMBER:
+ return toNumberVariationString(variation);
+ case InputType.TYPE_CLASS_DATETIME:
+ return toDatetimeVariationString(variation);
+ default:
+ return "";
}
- Log.i(TAG, "Flags:");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS))
- Log.i(TAG, " TYPE_TEXT_FLAG_NO_SUGGESTIONS");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE))
- Log.i(TAG, " TYPE_TEXT_FLAG_MULTI_LINE");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE))
- Log.i(TAG, " TYPE_TEXT_FLAG_IME_MULTI_LINE");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_WORDS))
- Log.i(TAG, " TYPE_TEXT_FLAG_CAP_WORDS");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES))
- Log.i(TAG, " TYPE_TEXT_FLAG_CAP_SENTENCES");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS))
- Log.i(TAG, " TYPE_TEXT_FLAG_CAP_CHARACTERS");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT))
- Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_CORRECT");
- if (0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE))
- Log.i(TAG, " TYPE_TEXT_FLAG_AUTO_COMPLETE");
+ }
+
+ private static String toTextVariationString(final int variation) {
+ switch (variation) {
+ case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
+ return " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
+ case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
+ return "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
+ case InputType.TYPE_TEXT_VARIATION_FILTER:
+ return "TYPE_TEXT_VARIATION_FILTER";
+ case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE:
+ return "TYPE_TEXT_VARIATION_LONG_MESSAGE";
+ case InputType.TYPE_TEXT_VARIATION_NORMAL:
+ return "TYPE_TEXT_VARIATION_NORMAL";
+ case InputType.TYPE_TEXT_VARIATION_PASSWORD:
+ return "TYPE_TEXT_VARIATION_PASSWORD";
+ case InputType.TYPE_TEXT_VARIATION_PERSON_NAME:
+ return "TYPE_TEXT_VARIATION_PERSON_NAME";
+ case InputType.TYPE_TEXT_VARIATION_PHONETIC:
+ return "TYPE_TEXT_VARIATION_PHONETIC";
+ case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
+ return "TYPE_TEXT_VARIATION_POSTAL_ADDRESS";
+ case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE:
+ return "TYPE_TEXT_VARIATION_SHORT_MESSAGE";
+ case InputType.TYPE_TEXT_VARIATION_URI:
+ return "TYPE_TEXT_VARIATION_URI";
+ case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
+ return "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD";
+ case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT:
+ return "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT";
+ case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
+ return "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS";
+ case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD:
+ return "TYPE_TEXT_VARIATION_WEB_PASSWORD";
+ default:
+ return String.format("unknownVariation<0x%08x>", variation);
+ }
+ }
+
+ private static String toNumberVariationString(final int variation) {
+ switch (variation) {
+ case InputType.TYPE_NUMBER_VARIATION_NORMAL:
+ return "TYPE_NUMBER_VARIATION_NORMAL";
+ case InputType.TYPE_NUMBER_VARIATION_PASSWORD:
+ return "TYPE_NUMBER_VARIATION_PASSWORD";
+ default:
+ return String.format("unknownVariation<0x%08x>", variation);
+ }
+ }
+
+ private static String toDatetimeVariationString(final int variation) {
+ switch (variation) {
+ case InputType.TYPE_DATETIME_VARIATION_NORMAL:
+ return "TYPE_DATETIME_VARIATION_NORMAL";
+ case InputType.TYPE_DATETIME_VARIATION_DATE:
+ return "TYPE_DATETIME_VARIATION_DATE";
+ case InputType.TYPE_DATETIME_VARIATION_TIME:
+ return "TYPE_DATETIME_VARIATION_TIME";
+ default:
+ return String.format("unknownVariation<0x%08x>", variation);
+ }
+ }
+
+ private static String toFlagsString(final int flags) {
+ final ArrayList<String> flagsArray = CollectionUtils.newArrayList();
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS))
+ flagsArray.add("TYPE_TEXT_FLAG_NO_SUGGESTIONS");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_MULTI_LINE))
+ flagsArray.add("TYPE_TEXT_FLAG_MULTI_LINE");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE))
+ flagsArray.add("TYPE_TEXT_FLAG_IME_MULTI_LINE");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_WORDS))
+ flagsArray.add("TYPE_TEXT_FLAG_CAP_WORDS");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES))
+ flagsArray.add("TYPE_TEXT_FLAG_CAP_SENTENCES");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS))
+ flagsArray.add("TYPE_TEXT_FLAG_CAP_CHARACTERS");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT))
+ flagsArray.add("TYPE_TEXT_FLAG_AUTO_CORRECT");
+ if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE))
+ flagsArray.add("TYPE_TEXT_FLAG_AUTO_COMPLETE");
+ return flagsArray.isEmpty() ? "" : Arrays.toString(flagsArray.toArray());
}
// Pretty print
@Override
public String toString() {
- return "\n mInputTypeNoAutoCorrect = " + mInputTypeNoAutoCorrect
- + "\n mIsSettingsSuggestionStripOn = " + mIsSettingsSuggestionStripOn
- + "\n mApplicationSpecifiedCompletionOn = " + mApplicationSpecifiedCompletionOn;
+ return String.format(
+ "%s: inputType=0x%08x%s%s%s%s%s targetApp=%s\n", getClass().getSimpleName(),
+ mInputType,
+ (mInputTypeNoAutoCorrect ? " noAutoCorrect" : ""),
+ (mIsPasswordField ? " password" : ""),
+ (mIsSettingsSuggestionStripOn ? " suggestionStrip" : ""),
+ (mApplicationSpecifiedCompletionOn ? " appSpecified" : ""),
+ (mShouldInsertSpacesAutomatically ? " insertSpaces" : ""),
+ mTargetApplicationPackageName);
}
- public static boolean inPrivateImeOptions(String packageName, String key,
- EditorInfo editorInfo) {
+ public static boolean inPrivateImeOptions(final String packageName, final String key,
+ final EditorInfo editorInfo) {
if (editorInfo == null) return false;
final String findingKey = (packageName != null) ? packageName + "." + key : key;
return StringUtils.containsInCommaSplittableText(findingKey, editorInfo.privateImeOptions);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 1631a200e..75ba24d75 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -171,10 +171,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onCreate() {
final Resources res = getOwnerInstance().getResources();
- mDelayUpdateSuggestions =
- res.getInteger(R.integer.config_delay_update_suggestions);
- mDelayUpdateShiftState =
- res.getInteger(R.integer.config_delay_update_shift_state);
+ mDelayUpdateSuggestions = res.getInteger(R.integer.config_delay_update_suggestions);
+ mDelayUpdateShiftState = res.getInteger(R.integer.config_delay_update_shift_state);
mDoubleSpacePeriodTimeout =
res.getInteger(R.integer.config_double_space_period_timeout);
}
@@ -339,12 +337,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void executePendingImsCallback(final LatinIME latinIme, final EditorInfo editorInfo,
boolean restarting) {
- if (mHasPendingFinishInputView)
+ if (mHasPendingFinishInputView) {
latinIme.onFinishInputViewInternal(mHasPendingFinishInput);
- if (mHasPendingFinishInput)
+ }
+ if (mHasPendingFinishInput) {
latinIme.onFinishInputInternal();
- if (mHasPendingStartInput)
+ }
+ if (mHasPendingStartInput) {
latinIme.onStartInputInternal(editorInfo, restarting);
+ }
resetPendingImsCallback();
}
@@ -579,9 +580,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
(mInputLogic.mSuggest == null) ? null : mInputLogic.mSuggest.mDictionaryFacilitator;
// Creates new dictionary facilitator for the new locale.
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
- new DictionaryFacilitatorForSuggest(this /* context */, locale,
- settingsValues, this /* DictionaryInitializationListener */,
- oldDictionaryFacilitator);
+ new DictionaryFacilitatorForSuggest(this /* context */, locale, settingsValues,
+ this /* DictionaryInitializationListener */, oldDictionaryFacilitator);
final Suggest newSuggest = new Suggest(locale, dictionaryFacilitator);
if (settingsValues.mCorrectionEnabled) {
newSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold);
@@ -658,7 +658,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
.findViewById(android.R.id.extractArea);
mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
- if (mSuggestionStripView != null) {
+ if (hasSuggestionStripView()) {
mSuggestionStripView.setListener(this, view);
}
if (LatinImeLogger.sVISUALDEBUG) {
@@ -738,13 +738,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
ResearchLogger.latinIME_onStartInputViewInternal(editorInfo, prefs);
}
if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
- Log.w(TAG, "Deprecated private IME option specified: "
- + editorInfo.privateImeOptions);
+ Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
}
if (InputAttributes.inPrivateImeOptions(getPackageName(), FORCE_ASCII, editorInfo)) {
- Log.w(TAG, "Deprecated private IME option specified: "
- + editorInfo.privateImeOptions);
+ Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
}
@@ -781,11 +779,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (null != suggest && null != currentLocale && !currentLocale.equals(suggest.mLocale)) {
initSuggest();
}
- if (mSuggestionStripView != null) {
- // This will set the punctuation suggestions if next word suggestion is off;
- // otherwise it will clear the suggestion strip.
- setNeutralSuggestionStrip();
- }
// Sometimes, while rotating, for some reason the framework tells the app we are not
// connected to it and that means we can't refresh the cache. In this case, schedule a
@@ -834,8 +827,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Space state must be updated before calling updateShiftState
switcher.updateShiftState();
}
- setSuggestionStripShownInternal(
- isSuggestionsStripVisible(), /* needsInputViewShown */ false);
+ // This will set the punctuation suggestions if next word suggestion is off;
+ // otherwise it will clear the suggestion strip.
+ setNeutralSuggestionStripInternal(false /* needsInputViewShown */);
mHandler.cancelUpdateSuggestionStrip();
mHandler.cancelDoubleSpacePeriodTimer();
@@ -894,12 +888,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
composingSpanStart, composingSpanEnd);
if (DEBUG) {
- Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
- + ", ose=" + oldSelEnd
- + ", nss=" + newSelStart
- + ", nse=" + newSelEnd
- + ", cs=" + composingSpanStart
- + ", ce=" + composingSpanEnd);
+ Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd
+ + ", nss=" + newSelStart + ", nse=" + newSelEnd
+ + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onUpdateSelection(oldSelStart, oldSelEnd,
@@ -983,7 +974,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
}
- if (!mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()) return;
+ if (!mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()) {
+ return;
+ }
if (applicationSpecifiedCompletions == null) {
setNeutralSuggestionStrip();
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -997,27 +990,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final ArrayList<SuggestedWords.SuggestedWordInfo> applicationSuggestedWords =
SuggestedWords.getFromApplicationSpecifiedCompletions(
applicationSpecifiedCompletions);
- final SuggestedWords suggestedWords = new SuggestedWords(
- applicationSuggestedWords, null /* rawSuggestions */,
- false /* typedWordValid */,
- false /* willAutoCorrect */,
- false /* isObsoleteSuggestions */,
- false /* isPrediction */);
- // When in fullscreen mode, show completions generated by the application
- setSuggestedWords(suggestedWords, true /* shouldShow */);
+ final SuggestedWords suggestedWords = new SuggestedWords(applicationSuggestedWords,
+ null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
+ false /* isObsoleteSuggestions */, false /* isPrediction */);
+ // When in fullscreen mode, show completions generated by the application forcibly
+ setSuggestedWords(suggestedWords, true /* isSuggestionStripVisible */,
+ true /* needsInputViewShown */);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
}
- private void setSuggestionStripShownInternal(final boolean shown,
+ private void setSuggestionStripShownInternal(final boolean isSuggestionStripVisible,
final boolean needsInputViewShown) {
// TODO: Modify this if we support suggestions with hard keyboard
- if (!onEvaluateInputViewShown() || null == mSuggestionStripView) {
+ if (!onEvaluateInputViewShown() || !hasSuggestionStripView()) {
return;
}
final boolean inputViewShown = mKeyboardSwitcher.isShowingMainKeyboardOrEmojiPalettes();
- final boolean shouldShowSuggestions = shown
+ final boolean shouldShowSuggestions = isSuggestionStripVisible
&& (needsInputViewShown ? inputViewShown : true);
if (shouldShowSuggestions) {
mSuggestionStripView.setVisibility(View.VISIBLE);
@@ -1057,7 +1048,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onComputeInsets(final InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets);
final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
- if (visibleKeyboardView == null || mSuggestionStripView == null) {
+ if (visibleKeyboardView == null || !hasSuggestionStripView()) {
return;
}
final int adjustedBackingHeight = getAdjustedBackingViewHeight();
@@ -1176,8 +1167,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onClick(final DialogInterface di, final int position) {
di.dismiss();
+ ImportantNoticeUtils.updateLastImportantNoticeVersion(context);
if (position == DialogInterface.BUTTON_POSITIVE) {
- ImportantNoticeUtils.updateLastImportantNoticeVersion(context);
setNeutralSuggestionStrip();
return;
}
@@ -1196,7 +1187,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void displaySettingsDialog() {
- if (isShowingOptionDialog()) return;
+ if (isShowingOptionDialog()) {
+ return;
+ }
showSubtypeSelectorAndSettings();
}
@@ -1256,8 +1249,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSubtypeSwitcher.switchToShortcutIME(this);
// Still call the *#onCodeInput methods for readability.
}
- mInputLogic.onCodeInput(codeToSend, keyX, keyY, mSettings.getCurrent(),
- mHandler, mKeyboardSwitcher);
+ mInputLogic.onCodeInput(codeToSend, keyX, keyY, mSettings.getCurrent(), mHandler,
+ mKeyboardSwitcher);
mKeyboardSwitcher.onCodeInput(codePoint);
}
@@ -1314,27 +1307,28 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Nothing to do so far.
}
- // TODO: remove this, read this directly from mInputLogic or something in the tests
- @UsedForTesting
- public boolean isShowingPunctuationList() {
- return mInputLogic.isShowingPunctuationList(mSettings.getCurrent());
- }
-
// TODO[IL]: Define a clear interface for this
- public boolean isSuggestionsStripVisible() {
- final SettingsValues currentSettings = mSettings.getCurrent();
- if (mSuggestionStripView == null)
+ public boolean isSuggestionStripVisible() {
+ if (!hasSuggestionStripView()) {
return false;
- if (mSuggestionStripView.isShowingAddToDictionaryHint())
+ }
+ if (mSuggestionStripView.isShowingAddToDictionaryHint()) {
return true;
- if (null == currentSettings)
+ }
+ final SettingsValues currentSettings = mSettings.getCurrent();
+ if (null == currentSettings) {
return false;
- if (ImportantNoticeUtils.shouldShowImportantNotice(this, currentSettings.mInputAttributes))
+ }
+ if (ImportantNoticeUtils.shouldShowImportantNotice(this,
+ currentSettings.mInputAttributes)) {
return true;
- if (!currentSettings.isSuggestionStripVisible())
+ }
+ if (!currentSettings.isSuggestionStripVisible()) {
return false;
- if (currentSettings.isApplicationSpecifiedCompletionsOn())
+ }
+ if (currentSettings.isApplicationSpecifiedCompletionsOn()) {
return true;
+ }
return currentSettings.isSuggestionsRequested();
}
@@ -1350,32 +1344,35 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void dismissAddToDictionaryHint() {
- if (null != mSuggestionStripView) {
- mSuggestionStripView.dismissAddToDictionaryHint();
+ if (!hasSuggestionStripView()) {
+ return;
}
+ mSuggestionStripView.dismissAddToDictionaryHint();
}
// TODO[IL]: Define a clear interface for this
- public void setSuggestedWords(final SuggestedWords suggestedWords, final boolean shouldShow) {
+ public void setSuggestedWords(final SuggestedWords suggestedWords,
+ final boolean isSuggestionStripVisible, final boolean needsInputViewShown) {
mInputLogic.setSuggestedWords(suggestedWords);
- if (mSuggestionStripView != null) {
- final SettingsValues currentSettings = mSettings.getCurrent();
- final boolean showSuggestions;
- if (SuggestedWords.EMPTY == suggestedWords
- || suggestedWords.isPunctuationSuggestions()
- || !currentSettings.isSuggestionsRequested()) {
- showSuggestions = !mSuggestionStripView.maybeShowImportantNoticeTitle(
- currentSettings.mInputAttributes);
- } else {
- showSuggestions = true;
- }
- if (showSuggestions) {
- mSuggestionStripView.setSuggestions(suggestedWords,
- SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
- }
- mKeyboardSwitcher.onAutoCorrectionStateChanged(suggestedWords.mWillAutoCorrect);
- setSuggestionStripShownInternal(shouldShow, true /* needsInputViewShown */);
+ if (!hasSuggestionStripView()) {
+ return;
+ }
+ final SettingsValues currentSettings = mSettings.getCurrent();
+ final boolean showSuggestions;
+ if (SuggestedWords.EMPTY == suggestedWords
+ || suggestedWords.isPunctuationSuggestions()
+ || !currentSettings.isSuggestionsRequested()) {
+ showSuggestions = !mSuggestionStripView.maybeShowImportantNoticeTitle(
+ currentSettings.mInputAttributes);
+ } else {
+ showSuggestions = true;
+ }
+ if (showSuggestions) {
+ mSuggestionStripView.setSuggestions(suggestedWords,
+ SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
}
+ mKeyboardSwitcher.onAutoCorrectionStateChanged(suggestedWords.mWillAutoCorrect);
+ setSuggestionStripShownInternal(isSuggestionStripVisible, needsInputViewShown);
}
// TODO[IL]: Move this out of LatinIME.
@@ -1414,9 +1411,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
suggest.getSuggestedWords(mInputLogic.mWordComposer,
mInputLogic.mWordComposer.getPreviousWordForSuggestion(),
- keyboard.getProximityInfo(),
- currentSettings.mBlockPotentiallyOffensive, currentSettings.mCorrectionEnabled,
- additionalFeaturesOptions, sessionId, sequenceNumber, callback);
+ keyboard.getProximityInfo(), currentSettings.mBlockPotentiallyOffensive,
+ currentSettings.mCorrectionEnabled, additionalFeaturesOptions, sessionId,
+ sequenceNumber, callback);
}
// TODO[IL]: Move this to InputLogic
@@ -1430,7 +1427,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// the "add to dictionary" hint, we need to revert to suggestions - although it is unclear
// how we can come here if it's displayed.
if (suggestedWords.size() > 1 || typedWord.length() <= 1
- || null == mSuggestionStripView || isShowingAddToDictionaryHint()) {
+ || !hasSuggestionStripView() || isShowingAddToDictionaryHint()) {
return suggestedWords;
} else {
final SuggestedWords punctuationList =
@@ -1440,10 +1437,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords);
return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */,
- false /* typedWordValid */,
- false /* hasAutoCorrectionCandidate */,
- true /* isObsoleteSuggestions */,
- false /* isPrediction */);
+ false /* typedWordValid */, false /* hasAutoCorrectionCandidate */,
+ true /* isObsoleteSuggestions */, false /* isPrediction */);
}
}
@@ -1463,7 +1458,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setNeutralSuggestionStrip();
} else {
mInputLogic.mWordComposer.setAutoCorrection(autoCorrection);
- setSuggestedWords(suggestedWords, isSuggestionsStripVisible());
+ setSuggestedWords(
+ suggestedWords, isSuggestionStripVisible(), true /* needsInputViewShown */);
}
// Cache the auto-correction in accessibility code so we can speak it if the user
// touches a key that will insert it.
@@ -1481,7 +1477,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void showAddToDictionaryHint(final String word) {
- if (null == mSuggestionStripView) return;
+ if (!hasSuggestionStripView()) {
+ return;
+ }
mSuggestionStripView.showAddToDictionaryHint(word);
}
@@ -1490,13 +1488,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// punctuation suggestions (if it's disabled).
@Override
public void setNeutralSuggestionStrip() {
+ setNeutralSuggestionStripInternal(true /* needsInputViewShown */);
+ }
+
+ private void setNeutralSuggestionStripInternal(final boolean needsInputViewShown) {
final SettingsValues currentSettings = mSettings.getCurrent();
- if (currentSettings.mBigramPredictionEnabled) {
- setSuggestedWords(SuggestedWords.EMPTY, isSuggestionsStripVisible());
- } else {
- setSuggestedWords(currentSettings.mSpacingAndPunctuations.mSuggestPuncList,
- isSuggestionsStripVisible());
- }
+ final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled
+ ? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
+ setSuggestedWords(neutralSuggestions, isSuggestionStripVisible(), needsInputViewShown);
}
// TODO: Make this private
@@ -1685,7 +1684,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: can this be removed somehow without breaking the tests?
@UsedForTesting
- /* package for test */ SuggestedWords getSuggestedWords() {
+ /* package for test */ SuggestedWords getSuggestedWordsForTest() {
// You may not use this method for anything else than debug
return DEBUG ? mInputLogic.mSuggestedWords : null;
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index eb1899ca2..ebad9bc0d 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -230,6 +230,9 @@ public final class RichInputConnection {
public void finishComposingText() {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
+ // TODO: this is not correct! The cursor is not necessarily after the composing text.
+ // In the practice right now this is only called when input ends so it will be reset so
+ // it works, but it's wrong and should be fixed.
mCommittedTextBeforeComposingText.append(mComposingText);
mComposingText.setLength(0);
if (null != mIC) {
@@ -244,6 +247,9 @@ public final class RichInputConnection {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
mCommittedTextBeforeComposingText.append(text);
+ // TODO: the following is exceedingly error-prone. Right now when the cursor is in the
+ // middle of the composing word mComposingText only holds the part of the composing text
+ // that is before the cursor, so this actually works, but it's terribly confusing. Fix this.
mExpectedSelStart += text.length() - mComposingText.length();
mExpectedSelEnd = mExpectedSelStart;
mComposingText.setLength(0);
@@ -347,6 +353,9 @@ public final class RichInputConnection {
public void deleteSurroundingText(final int beforeLength, final int afterLength) {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
+ // TODO: the following is incorrect if the cursor is not immediately after the composition.
+ // Right now we never come here in this case because we reset the composing state before we
+ // come here in this case, but we need to fix this.
final int remainingChars = mComposingText.length() - beforeLength;
if (remainingChars >= 0) {
mComposingText.setLength(remainingChars);
@@ -447,8 +456,12 @@ public final class RichInputConnection {
getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE + (end - start), 0);
mCommittedTextBeforeComposingText.setLength(0);
if (!TextUtils.isEmpty(textBeforeCursor)) {
+ // The cursor is not necessarily at the end of the composing text, but we have its
+ // position in mExpectedSelStart and mExpectedSelEnd. In this case we want the start
+ // of the text, so we should use mExpectedSelStart. In other words, the composing
+ // text starts (mExpectedSelStart - start) characters before the end of textBeforeCursor
final int indexOfStartOfComposingText =
- Math.max(textBeforeCursor.length() - (end - start), 0);
+ Math.max(textBeforeCursor.length() - (mExpectedSelStart - start), 0);
mComposingText.append(textBeforeCursor.subSequence(indexOfStartOfComposingText,
textBeforeCursor.length()));
mCommittedTextBeforeComposingText.append(
@@ -544,6 +557,9 @@ public final class RichInputConnection {
final int checkLength = LOOKBACK_CHARACTER_NUM - 1;
final String reference = prev.length() <= checkLength ? prev.toString()
: prev.subSequence(prev.length() - checkLength, prev.length()).toString();
+ // TODO: right now the following works because mComposingText holds the part of the
+ // composing text that is before the cursor, but this is very confusing. We should
+ // fix it.
final StringBuilder internal = new StringBuilder()
.append(mCommittedTextBeforeComposingText).append(mComposingText);
if (internal.length() > checkLength) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 9bf9d1f45..3fc2cf8fd 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -198,7 +198,7 @@ public final class InputLogic {
final SuggestedWords suggestedWords = mSuggestedWords;
final String suggestion = suggestionInfo.mWord;
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
- if (suggestion.length() == 1 && isShowingPunctuationList(settingsValues)) {
+ if (suggestion.length() == 1 && suggestedWords.isPunctuationSuggestions()) {
// Word separators are suggested before the user inputs something.
// So, LatinImeLogger logs "" as a user's input.
LatinImeLogger.logOnManualSuggestion("", suggestion, index, suggestedWords);
@@ -821,7 +821,7 @@ public final class InputLogic {
if (maybeDoubleSpacePeriod(settingsValues, handler)) {
keyboardSwitcher.updateShiftState();
mSpaceState = SpaceState.DOUBLE;
- } else if (!isShowingPunctuationList(settingsValues)) {
+ } else if (!mSuggestedWords.isPunctuationSuggestions()) {
mSpaceState = SpaceState.WEAK;
}
}
@@ -1456,15 +1456,6 @@ public final class InputLogic {
}
/**
- * Find out if the punctuation list is shown in the suggestion strip.
- * @return whether the current suggestions are the punctuation list.
- */
- // TODO: make this private. It's used through LatinIME for tests.
- public boolean isShowingPunctuationList(final SettingsValues settingsValues) {
- return settingsValues.mSpacingAndPunctuations.mSuggestPuncList == mSuggestedWords;
- }
-
- /**
* Factor in auto-caps and manual caps and compute the current caps mode.
* @param settingsValues the current settings values.
* @param keyboardShiftMode the current shift mode of the keyboard. See
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 90b9692c3..1f80c4cca 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -233,7 +233,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
return false;
}
final int width = getWidth();
- if (width <= 0) return false;
+ if (width <= 0) {
+ return false;
+ }
mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, width);
mStripVisibilityGroup.showImportantNoticeStrip();
mImportantNoticeStrip.setOnClickListener(this);
@@ -429,9 +431,11 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
}
@Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
// Called by the framework when the size is known. Show the important notice if applicable.
// This may be overriden by showing suggestions later, if applicable.
- maybeShowImportantNoticeTitle(Settings.getInstance().getCurrent().mInputAttributes);
+ if (oldw <= 0 && w > 0) {
+ maybeShowImportantNoticeTitle(Settings.getInstance().getCurrent().mInputAttributes);
+ }
}
}
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
index 32c4950da..2f41ce9ce 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryList.java
@@ -61,12 +61,17 @@ public class UserDictionaryList extends PreferenceFragment {
if (null == cursor) {
// The user dictionary service is not present or disabled. Return null.
return null;
- } else if (cursor.moveToFirst()) {
- final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
- do {
- final String locale = cursor.getString(columnIndex);
- localeSet.add(null != locale ? locale : "");
- } while (cursor.moveToNext());
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
+ do {
+ final String locale = cursor.getString(columnIndex);
+ localeSet.add(null != locale ? locale : "");
+ } while (cursor.moveToNext());
+ }
+ } finally {
+ cursor.close();
}
if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
// For ICS, we need to show "For all languages" in case that the keyboard locale
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
index 7571e87c5..220efb5d3 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionarySettings.java
@@ -140,6 +140,8 @@ public class UserDictionarySettings extends ListFragment {
}
mLocale = locale;
+ // WARNING: The following cursor is never closed! TODO: don't put that in a member, and
+ // make sure all cursors are correctly closed.
mCursor = createCursor(locale);
TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);
emptyView.setText(R.string.user_dict_settings_empty_text);