diff options
Diffstat (limited to 'java/src')
16 files changed, 204 insertions, 178 deletions
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java index 12fdd69b9..ee142d845 100644 --- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java +++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java @@ -173,7 +173,7 @@ public final class ActionBatch { final long downloadId = UpdateHandler.registerDownloadRequest(manager, request, db, mWordList.mId, mWordList.mVersion); Log.i(TAG, String.format("Starting the dictionary download with version:" - + " %d and Url: %s" + mWordList.mVersion, uri)); + + " %d and Url: %s", mWordList.mVersion, uri)); DebugLogUtils.l("Starting download of", uri, "with id", downloadId); PrivateLog.log("Starting download of " + uri + ", id : " + downloadId); } diff --git a/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java b/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java index 3d0e29ed0..3cd822a3c 100644 --- a/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java +++ b/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java @@ -22,6 +22,8 @@ import android.content.SharedPreferences; public final class CommonPreferences { private static final String COMMON_PREFERENCES_NAME = "LatinImeDictPrefs"; + public static final String PREF_FORCE_DOWNLOAD_DICT = "pref_key_force_download_dict"; + public static SharedPreferences getCommonPreferences(final Context context) { return context.getSharedPreferences(COMMON_PREFERENCES_NAME, 0); } @@ -37,4 +39,14 @@ public final class CommonPreferences { editor.putBoolean(id, false); editor.apply(); } + + public static boolean isForceDownloadDict(Context context) { + return getCommonPreferences(context).getBoolean(PREF_FORCE_DOWNLOAD_DICT, false); + } + + public static void setForceDownloadDict(Context context, boolean forceDownload) { + SharedPreferences.Editor editor = getCommonPreferences(context).edit(); + editor.putBoolean(PREF_FORCE_DOWNLOAD_DICT, forceDownload); + editor.apply(); + } } diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java index c678f081d..bbdf2a380 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java @@ -25,6 +25,7 @@ import android.os.IBinder; import android.util.Log; import android.widget.Toast; +import com.android.inputmethod.latin.BinaryDictionaryFileDumper; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.common.LocaleUtils; @@ -192,13 +193,26 @@ public final class DictionaryService extends Service { static void dispatchBroadcast(final Context context, final Intent intent) { if (DATE_CHANGED_INTENT_ACTION.equals(intent.getAction())) { + // Do not force download dictionaries on date change updates. + CommonPreferences.setForceDownloadDict(context, false); // This happens when the date of the device changes. This normally happens // at midnight local time, but it may happen if the user changes the date // by hand or something similar happens. checkTimeAndMaybeSetupUpdateAlarm(context); } else if (DictionaryPackConstants.UPDATE_NOW_INTENT_ACTION.equals(intent.getAction())) { // Intent to trigger an update now. - UpdateHandler.tryUpdate(context, false); + UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context)); + } else if (DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION.equals( + intent.getAction())) { + // Enable force download of dictionaries irrespective of wifi or metered connection. + CommonPreferences.setForceDownloadDict(context, true); + + // Initialize the client Db. + final String mClientId = context.getString(R.string.dictionary_pack_client_id); + BinaryDictionaryFileDumper.initializeClientRecordHelper(context, mClientId); + + // Updates the metadata and the download the dictionaries. + UpdateHandler.tryUpdate(context, true); } else { UpdateHandler.downloadFinished(context, intent); } @@ -249,7 +263,7 @@ public final class DictionaryService extends Service { */ public static void updateNowIfNotUpdatedInAVeryLongTime(final Context context) { if (!isLastUpdateAtLeastThisOld(context, VERY_LONG_TIME_MILLIS)) return; - UpdateHandler.tryUpdate(context, false); + UpdateHandler.tryUpdate(context, CommonPreferences.isForceDownloadDict(context)); } /** diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java index 14e005007..88ea4e6c3 100644 --- a/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java +++ b/java/src/com/android/inputmethod/dictionarypack/DictionarySettingsFragment.java @@ -28,6 +28,7 @@ import android.database.Cursor; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceFragment; @@ -106,16 +107,27 @@ public final class DictionarySettingsFragment extends PreferenceFragment @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { - final String metadataUri = - MetadataDbHelper.getMetadataUriAsString(getActivity(), mClientId); - // We only add the "Refresh" button if we have a non-empty URL to refresh from. If the - // URL is empty, of course we can't refresh so it makes no sense to display this. - if (!TextUtils.isEmpty(metadataUri)) { - mUpdateNowMenu = - menu.add(Menu.NONE, MENU_UPDATE_NOW, 0, R.string.check_for_updates_now); - mUpdateNowMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - refreshNetworkState(); - } + new AsyncTask<Void, Void, String>() { + @Override + protected String doInBackground(Void... params) { + return MetadataDbHelper.getMetadataUriAsString(getActivity(), mClientId); + } + + @Override + protected void onPostExecute(String metadataUri) { + // We only add the "Refresh" button if we have a non-empty URL to refresh from. If + // the URL is empty, of course we can't refresh so it makes no sense to display + // this. + if (!TextUtils.isEmpty(metadataUri)) { + if (mUpdateNowMenu == null) { + mUpdateNowMenu = menu.add(Menu.NONE, MENU_UPDATE_NOW, 0, + R.string.check_for_updates_now); + mUpdateNowMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + refreshNetworkState(); + } + } + }.execute(); } @Override @@ -124,18 +136,25 @@ public final class DictionarySettingsFragment extends PreferenceFragment mChangedSettings = false; UpdateHandler.registerUpdateEventListener(this); final Activity activity = getActivity(); - if (!MetadataDbHelper.isClientKnown(activity, mClientId)) { - Log.i(TAG, "Unknown dictionary pack client: " + mClientId + ". Requesting info."); - final Intent unknownClientBroadcast = - new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT); - unknownClientBroadcast.putExtra( - DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId); - activity.sendBroadcast(unknownClientBroadcast); - } final IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); getActivity().registerReceiver(mConnectivityChangedReceiver, filter); refreshNetworkState(); + + new Thread("onResume") { + @Override + public void run() { + if (!MetadataDbHelper.isClientKnown(activity, mClientId)) { + Log.i(TAG, "Unknown dictionary pack client: " + mClientId + + ". Requesting info."); + final Intent unknownClientBroadcast = + new Intent(DictionaryPackConstants.UNKNOWN_DICTIONARY_PROVIDER_CLIENT); + unknownClientBroadcast.putExtra( + DictionaryPackConstants.DICTIONARY_PROVIDER_CLIENT_EXTRA, mClientId); + activity.sendBroadcast(unknownClientBroadcast); + } + } + }.start(); } @Override @@ -375,8 +394,13 @@ public final class DictionarySettingsFragment extends PreferenceFragment private void cancelRefresh() { UpdateHandler.unregisterUpdateEventListener(this); final Context context = getActivity(); - UpdateHandler.cancelUpdate(context, mClientId); - stopLoadingAnimation(); + new Thread("cancelByHand") { + @Override + public void run() { + UpdateHandler.cancelUpdate(context, mClientId); + stopLoadingAnimation(); + } + }.start(); } private void startLoadingAnimation() { diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java index b00a811bb..a2789cc1a 100644 --- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java +++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java @@ -264,6 +264,8 @@ public class MetadataDbHelper extends SQLiteOpenHelper { */ @Override public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + // Allow automatic download of dictionaries on upgrading the database. + CommonPreferences.setForceDownloadDict(mContext, true); if (METADATA_DATABASE_INITIAL_VERSION == oldVersion && METADATA_DATABASE_VERSION_WITH_CLIENTID <= newVersion && CURRENT_METADATA_DATABASE_VERSION >= newVersion) { diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java index f05db9dab..30ff0b8ee 100644 --- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java +++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java @@ -449,6 +449,8 @@ public final class UpdateHandler { // download, so we are pretty sure it's alive. It's theoretically possible that it's // disabled right inbetween the firing of the intent and the control reaching here. + boolean dictionaryDownloaded = false; + for (final DownloadRecord record : recordList) { // downloadSuccessful is not final because we may still have exceptions from now on boolean downloadSuccessful = false; @@ -463,9 +465,15 @@ public final class UpdateHandler { final SQLiteDatabase db = MetadataDbHelper.getDb(context, record.mClientId); publishUpdateWordListCompleted(context, downloadSuccessful, fileId, db, record.mAttributes, record.mClientId); + dictionaryDownloaded = true; } } } + + if (dictionaryDownloaded) { + // Disable the force download after downloading the dictionaries. + CommonPreferences.setForceDownloadDict(context, false); + } // Now that we're done using it, we can remove this download from DLManager manager.remove(fileId); } @@ -804,7 +812,7 @@ public final class UpdateHandler { } else { final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId); if (newInfo.mVersion == currentInfo.mVersion) { - if (newInfo.mRemoteFilename == currentInfo.mRemoteFilename) { + if (TextUtils.equals(newInfo.mRemoteFilename, currentInfo.mRemoteFilename)) { // If the dictionary url hasn't changed, we should preserve the retryCount. newInfo.mRetryCount = currentInfo.mRetryCount; } @@ -820,7 +828,8 @@ public final class UpdateHandler { actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo)); if (status == MetadataDbHelper.STATUS_INSTALLED || status == MetadataDbHelper.STATUS_DISABLED) { - actions.add(new ActionBatch.StartDownloadAction(clientId, newInfo, false)); + actions.add(new ActionBatch.StartDownloadAction( + clientId, newInfo, CommonPreferences.isForceDownloadDict(context))); } else { // Pass true to ForgetAction: this is indeed an update to a non-installed // word list, so activate status == AVAILABLE check @@ -973,8 +982,10 @@ public final class UpdateHandler { // change the shared preferences. So there is no way for a word list that has been // auto-installed once to get auto-installed again, and that's what we want. final ActionBatch actions = new ActionBatch(); - actions.add(new ActionBatch.StartDownloadAction(clientId, - WordListMetadata.createFromContentValues(installCandidate), false)); + actions.add(new ActionBatch.StartDownloadAction( + clientId, + WordListMetadata.createFromContentValues(installCandidate), + CommonPreferences.isForceDownloadDict(context))); final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN); // We are in a content provider: we can't do any UI at all. We have to defer the displaying // itself to the service. Also, we only display this when the user does not have a @@ -1020,8 +1031,9 @@ public final class UpdateHandler { || MetadataDbHelper.STATUS_DELETING == status) { actions.add(new ActionBatch.EnableAction(clientId, wordListMetaData)); } else if (MetadataDbHelper.STATUS_AVAILABLE == status) { + boolean forceDownloadDict = CommonPreferences.isForceDownloadDict(context); actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData, - allowDownloadOnMeteredData)); + forceDownloadDict || allowDownloadOnMeteredData)); } else { Log.e(TAG, "Unexpected state of the word list for markAsUsed : " + status); } @@ -1133,7 +1145,8 @@ public final class UpdateHandler { context, clientId, wordlistId, version); final ActionBatch actions = new ActionBatch(); - actions.add(new ActionBatch.StartDownloadAction(clientId, wordListMetaData, false)); + actions.add(new ActionBatch.StartDownloadAction( + clientId, wordListMetaData, CommonPreferences.isForceDownloadDict(context))); actions.execute(context, new LogProblemReporter(TAG)); } else { if (DEBUG) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 6b49f9aa6..d5dff10db 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -17,7 +17,6 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Keyboard; @@ -28,6 +27,7 @@ import com.android.inputmethod.latin.utils.SuggestionResults; import java.io.File; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -172,5 +172,5 @@ public interface DictionaryFacilitator { void dumpDictionaryForDebug(final String dictName); - ArrayList<Pair<String, DictionaryStats>> getStatsOfEnabledSubDicts(); + @Nonnull List<DictionaryStats> getDictionaryStats(final Context context); } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java index e5d770aee..9ce92da9e 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java @@ -19,7 +19,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.text.TextUtils; import android.util.Log; -import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.keyboard.Keyboard; @@ -39,6 +38,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -644,12 +644,12 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { } @Override - public ArrayList<Pair<String, DictionaryStats>> getStatsOfEnabledSubDicts() { - final ArrayList<Pair<String, DictionaryStats>> statsOfEnabledSubDicts = new ArrayList<>(); + @Nonnull public List<DictionaryStats> getDictionaryStats(final Context context) { + final ArrayList<DictionaryStats> statsOfEnabledSubDicts = new ArrayList<>(); for (final String dictType : DYNAMIC_DICTIONARY_TYPES) { final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictType); if (dictionary == null) continue; - statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats())); + statsOfEnabledSubDicts.add(dictionary.getDictionaryStats()); } return statsOfEnabledSubDicts; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryStats.java b/java/src/com/android/inputmethod/latin/DictionaryStats.java index 5dd39d3d6..a6b37aa8f 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryStats.java +++ b/java/src/com/android/inputmethod/latin/DictionaryStats.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import java.io.File; +import java.math.BigDecimal; import java.util.Locale; public class DictionaryStats { @@ -26,18 +27,54 @@ public class DictionaryStats { public final String mDictName; public final String mDictFilePath; public final long mDictFileSize; - - public final int mUnigramCount; - public final int mNgramCount; - // TODO: Add more members. + public final int mContentVersion; public DictionaryStats(final Locale locale, final String dictName, final File dictFile, - final int unigramCount, final int ngramCount) { + final int contentVersion) { mLocale = locale; mDictName = dictName; - mDictFilePath = dictFile.getAbsolutePath(); - mDictFileSize = dictFile.length(); - mUnigramCount = unigramCount; - mNgramCount = ngramCount; + mDictFilePath = (dictFile == null) ? null : dictFile.getName(); + mDictFileSize = (dictFile == null || !dictFile.exists()) ? 0 : dictFile.length(); + mContentVersion = contentVersion; + } + + public String getFileSizeString() { + if (mDictFileSize == 0) { + return "0"; + } + BigDecimal bytes = new BigDecimal(mDictFileSize); + BigDecimal kb = bytes.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP); + if (kb.longValue() == 0) { + return bytes.toString() + " bytes"; + } + BigDecimal mb = kb.divide(new BigDecimal(1024), 2, BigDecimal.ROUND_HALF_UP); + if (mb.longValue() == 0) { + return kb.toString() + " kb"; + } + return mb.toString() + " Mb"; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(mDictName); + if (mDictName.equals(Dictionary.TYPE_MAIN)) { + builder.append(" ("); + builder.append(mContentVersion); + builder.append(")"); + } + builder.append(": "); + builder.append(mDictFilePath); + builder.append(" / "); + builder.append(getFileSizeString()); + return builder.toString(); + } + + public static String toString(final Iterable<DictionaryStats> stats) { + final StringBuilder builder = new StringBuilder("LM Stats"); + for (DictionaryStats stat : stats) { + builder.append("\n "); + builder.append(stat.toString()); + } + return builder.toString(); } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 80daedd50..1ef7061fb 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -646,16 +646,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }); } - static int parseEntryCount(final String entryCountStr) { - int entryCount; - try { - entryCount = Integer.parseInt(entryCountStr); - } catch (final NumberFormatException e) { - entryCount = DictionaryStats.NOT_AN_ENTRY_COUNT; - } - return entryCount; - } - public DictionaryStats getDictionaryStats() { reloadDictionaryIfRequired(); final String dictName = mDictName; @@ -664,22 +654,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() { @Override public void run() { - final BinaryDictionary binaryDictionary = getBinaryDictionary(); - if (binaryDictionary == null) { - result.set(new DictionaryStats(mLocale, dictName, dictFile, - DictionaryStats.NOT_AN_ENTRY_COUNT, - DictionaryStats.NOT_AN_ENTRY_COUNT)); - return; - } - final int unigramCount = parseEntryCount( - binaryDictionary.getPropertyForGettingStats( - BinaryDictionary.MAX_UNIGRAM_COUNT_QUERY)); - // TODO: Get dedicated entry counts for bigram, trigram, and so on. - final int ngramCount = parseEntryCount(binaryDictionary.getPropertyForGettingStats( - BinaryDictionary.MAX_BIGRAM_COUNT_QUERY)); - // TODO: Get more information from dictionary. - result.set(new DictionaryStats(mLocale, dictName, dictFile, unigramCount, - ngramCount)); + result.set(new DictionaryStats(mLocale, dictName, dictFile, 0)); } }); return result.get(null /* defaultValue */, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS); diff --git a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java index 5c3abd2db..2a69d3650 100644 --- a/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java +++ b/java/src/com/android/inputmethod/latin/SystemBroadcastReceiver.java @@ -27,6 +27,8 @@ import android.util.Log; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import com.android.inputmethod.dictionarypack.CommonPreferences; +import com.android.inputmethod.dictionarypack.DictionaryPackConstants; import com.android.inputmethod.keyboard.KeyboardLayoutSet; import com.android.inputmethod.latin.setup.SetupActivity; import com.android.inputmethod.latin.utils.UncachedInputMethodManagerUtils; @@ -70,6 +72,7 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { final InputMethodSubtype[] additionalSubtypes = richImm.getAdditionalSubtypes(); richImm.setAdditionalInputMethodSubtypes(additionalSubtypes); toggleAppIcon(context); + downloadLatestDictionaries(context); } else if (Intent.ACTION_BOOT_COMPLETED.equals(intentAction)) { Log.i(TAG, "Boot has been completed"); toggleAppIcon(context); @@ -97,6 +100,12 @@ public final class SystemBroadcastReceiver extends BroadcastReceiver { } } + private void downloadLatestDictionaries(Context context) { + final Intent updateIntent = new Intent( + DictionaryPackConstants.INIT_AND_UPDATE_NOW_INTENT_ACTION); + context.sendBroadcast(updateIntent); + } + private static void toggleAppIcon(final Context context) { final int appInfoFlags = context.getApplicationInfo().flags; final boolean isSystemApp = (appInfoFlags & ApplicationInfo.FLAG_SYSTEM) > 0; diff --git a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java index f7c5f6760..62834cd2a 100644 --- a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java @@ -49,7 +49,7 @@ import java.util.TreeSet; */ public final class CorrectionSettingsFragment extends SubScreenFragment { private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false; - private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS = + private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS || Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2; @@ -61,8 +61,6 @@ public final class CorrectionSettingsFragment extends SubScreenFragment { final Context context = getActivity(); final PackageManager pm = context.getPackageManager(); - ensureConsistencyOfAutoCorrectionSettings(); - final Preference dictionaryLink = findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY); final Intent intent = dictionaryLink.getIntent(); intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName()); @@ -74,7 +72,7 @@ public final class CorrectionSettingsFragment extends SubScreenFragment { final Preference editPersonalDictionary = findPreference(Settings.PREF_EDIT_PERSONAL_DICTIONARY); final Intent editPersonalDictionaryIntent = editPersonalDictionary.getIntent(); - final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTIGS ? null + final ResolveInfo ri = USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS ? null : pm.resolveActivity( editPersonalDictionaryIntent, PackageManager.MATCH_DEFAULT_ONLY); if (ri == null) { @@ -82,19 +80,6 @@ public final class CorrectionSettingsFragment extends SubScreenFragment { } } - @Override - public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { - ensureConsistencyOfAutoCorrectionSettings(); - } - - private void ensureConsistencyOfAutoCorrectionSettings() { - final TwoStatePreference autoCorrectionPref = (TwoStatePreference) - findPreference(Settings.PREF_AUTO_CORRECTION); - if (!autoCorrectionPref.isChecked()) { - setPreferenceEnabled(Settings.PREF_BIGRAM_PREDICTIONS, false); - } - } - private void overwriteUserDictionaryPreference(final Preference userDictionaryPreference) { final Activity activity = getActivity(); final TreeSet<String> localeList = UserDictionaryList.getUserDictionaryLocalesSet(activity); diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java index dee4811c9..9975277e4 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java @@ -50,7 +50,7 @@ public final class SettingsActivity extends PreferenceActivity { } StatsUtils.onSettingsActivity( intent.hasExtra(EXTRA_ENTRY_KEY) ? intent.getStringExtra(EXTRA_ENTRY_KEY) - : intent.getStringExtra(EXTRA_ENTRY_VALUE_SYSTEM_SETTINGS)); + : EXTRA_ENTRY_VALUE_SYSTEM_SETTINGS); } @Override diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java index b98c53af4..f5455e3db 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java @@ -16,10 +16,12 @@ package com.android.inputmethod.latin.settings; +import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceScreen; +import android.provider.Settings.Secure; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -68,13 +70,23 @@ public final class SettingsFragment extends InputMethodSettingsFragment { @Override public boolean onOptionsItemSelected(final MenuItem item) { + final Activity activity = getActivity(); + final int setupStatus = Secure.getInt( + activity.getContentResolver(), + "user_setup_complete", + 0 /* default */); + if (setupStatus == 0) { + // If setup is not complete, it's not safe to launch Help or other activities + // because they might go to the Play Store. See b/19866981. + return true; + } final int itemId = item.getItemId(); if (itemId == MENU_HELP_AND_FEEDBACK) { - FeedbackUtils.showHelpAndFeedbackForm(getActivity()); + FeedbackUtils.showHelpAndFeedbackForm(activity); return true; } if (itemId == MENU_ABOUT) { - final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(getActivity()); + final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(activity); if (aboutIntent != null) { startActivity(aboutIntent); return true; diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index fd567f49d..d8e332370 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -22,11 +22,13 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.text.TextUtils; import android.util.Log; +import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.AssetFileAddress; import com.android.inputmethod.latin.BinaryDictionaryGetter; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.common.LocaleUtils; import com.android.inputmethod.latin.define.DecoderSpecificConstants; import com.android.inputmethod.latin.makedict.DictionaryHeader; @@ -37,6 +39,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; @@ -69,12 +72,11 @@ public class DictionaryInfoUtils { public final Locale mLocale; @Nullable public final String mDescription; - @Nonnull public final AssetFileAddress mFileAddress; public final int mVersion; public DictionaryInfo(@Nonnull final String id, @Nonnull final Locale locale, - @Nullable final String description, @Nonnull final AssetFileAddress fileAddress, + @Nullable final String description, @Nullable final AssetFileAddress fileAddress, final int version) { mId = id; mLocale = locale; @@ -88,10 +90,12 @@ public class DictionaryInfoUtils { values.put(WORDLISTID_COLUMN, mId); values.put(LOCALE_COLUMN, mLocale.toString()); values.put(DESCRIPTION_COLUMN, mDescription); - values.put(LOCAL_FILENAME_COLUMN, mFileAddress.mFilename); + values.put(LOCAL_FILENAME_COLUMN, + mFileAddress != null ? mFileAddress.mFilename : ""); values.put(DATE_COLUMN, TimeUnit.MILLISECONDS.toSeconds( - new File(mFileAddress.mFilename).lastModified())); - values.put(FILESIZE_COLUMN, mFileAddress.mLength); + mFileAddress != null ? new File(mFileAddress.mFilename).lastModified() : 0)); + values.put(FILESIZE_COLUMN, + mFileAddress != null ? mFileAddress.mLength : 0); values.put(VERSION_COLUMN, mVersion); return values; } @@ -360,7 +364,6 @@ public class DictionaryInfoUtils { * @param locale Locale for this file. * @return information of the specified dictionary. */ - @Nullable private static DictionaryInfo createDictionaryInfoFromFileAddress( final AssetFileAddress fileAddress, Locale locale) { final String id = getMainDictId(locale); @@ -370,6 +373,17 @@ public class DictionaryInfoUtils { return new DictionaryInfo(id, locale, description, fileAddress, version); } + /** + * Returns dictionary information for the given locale. + */ + private static DictionaryInfo createDictionaryInfoFromLocale(Locale locale) { + final String id = getMainDictId(locale); + final int version = -1; + final String description = SubtypeLocaleUtils + .getSubtypeLocaleDisplayName(locale.toString()); + return new DictionaryInfo(id, locale, description, null, version); + } + private static void addOrUpdateDictInfo(final ArrayList<DictionaryInfo> dictList, final DictionaryInfo newElement) { final Iterator<DictionaryInfo> iter = dictList.iterator(); @@ -441,6 +455,17 @@ public class DictionaryInfoUtils { addOrUpdateDictInfo(dictList, dictionaryInfo); } + // Generate the dictionary information from the enabled subtypes. This will not + // overwrite the real records. + RichInputMethodManager.init(context); + List<InputMethodSubtype> enabledSubtypes = RichInputMethodManager + .getInstance().getMyEnabledInputMethodSubtypeList(true); + for (InputMethodSubtype subtype : enabledSubtypes) { + Locale locale = LocaleUtils.constructLocaleFromString(subtype.getLocale()); + DictionaryInfo dictionaryInfo = createDictionaryInfoFromLocale(locale); + addOrUpdateDictInfo(dictList, dictionaryInfo); + } + return dictList; } diff --git a/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java b/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java deleted file mode 100644 index 1bd8f314c..000000000 --- a/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.utils; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.os.UserHandle; -import android.os.UserManager; -import android.util.Log; - -import com.android.inputmethod.annotations.UsedForTesting; - -import java.util.List; - -/** - * Utility for determining if the device has managed profiles. - */ -public class ManagedProfileUtils { - private static final boolean DEBUG = false; - private static final String TAG = ManagedProfileUtils.class.getSimpleName(); - - private static ManagedProfileUtils INSTANCE = new ManagedProfileUtils(); - private static ManagedProfileUtils sTestInstance; - - private ManagedProfileUtils() { - // This utility class is not publicly instantiable. - } - - @UsedForTesting - public static void setTestInstance(final ManagedProfileUtils testInstance) { - sTestInstance = testInstance; - } - - public static ManagedProfileUtils getInstance() { - return sTestInstance == null ? INSTANCE : sTestInstance; - } - - /** - * Note that {@link UserManager#getUserProfiles} has been introduced - * in API level 21 (Build.VERSION_CODES.LOLLIPOP). - */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public boolean hasManagedWorkProfile(final Context context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - return false; - } - - final UserManager userManagerService = - (UserManager) context.getSystemService(Context.USER_SERVICE); - if (userManagerService != null) { - if (DEBUG) { - Log.d(TAG, "Detecting managed profile..."); - } - final List<UserHandle> userProfiles = userManagerService.getUserProfiles(); - if (userProfiles.size() > 1) { - if (DEBUG) { - Log.d(TAG, "More than one user profile => Managed profile exists."); - } - return true; - } - } - if (DEBUG) { - Log.d(TAG, "Managed profile not detected."); - } - return false; - } -} |