Merge "Check for accounts when enabling sync features."
diff --git a/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
index df0e3f0..13caea4 100644
--- a/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
+++ b/java-overridable/src/com/android/inputmethod/dictionarypack/DictionaryPackConstants.java
@@ -62,4 +62,11 @@
      */
     public static final String UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
             + ".UPDATE_NOW";
+
+    /**
+     * The intent action to inform the dictionary provider to initialize the db
+     * and update now.
+     */
+    public static final String INIT_AND_UPDATE_NOW_INTENT_ACTION = DICTIONARY_DOMAIN
+            + ".INIT_AND_UPDATE_NOW";
 }
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
new file mode 100644
index 0000000..ef1872b
--- /dev/null
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
@@ -0,0 +1,43 @@
+/*
+ * 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.content.Context;
+
+import com.android.inputmethod.annotations.UsedForTesting;
+
+public class ManagedProfileUtils {
+    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;
+    }
+
+    public boolean hasWorkProfile(final Context context) {
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 210d9a9..f58c401 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -144,6 +144,7 @@
                 <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
                 <action android:name="android.intent.action.DATE_CHANGED" />
                 <action android:name="com.android.inputmethod.dictionarypack.aosp.UPDATE_NOW" />
+                <action android:name="com.android.inputmethod.dictionarypack.aosp.INIT_AND_UPDATE_NOW" />
             </intent-filter>
         </receiver>
 
diff --git a/java/res/values/config-dictionary-pack.xml b/java/res/values/config-dictionary-pack.xml
index d076af4..bf52de8 100644
--- a/java/res/values/config-dictionary-pack.xml
+++ b/java/res/values/config-dictionary-pack.xml
@@ -25,6 +25,6 @@
     <bool name="allow_over_roaming">false</bool>
     <bool name="dict_downloads_visible_in_download_UI">false</bool>
     <bool name="metadata_downloads_visible_in_download_UI">false</bool>
-    <bool name="display_notification_for_auto_update">false</bool>
-    <bool name="display_notification_for_user_requested_update">false</bool>
+    <bool name="display_notification_for_auto_update">true</bool>
+    <bool name="display_notification_for_user_requested_update">true</bool>
 </resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 54579f2..5655a55 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -62,9 +62,9 @@
     <string name="cloud_sync_summary_disabled">Sync your personal dictionary across devices</string>
     <!-- Option title for starting the sync cycle now. [CHAR LIMIT=33]-->
     <string name="sync_now_title">Sync now</string>
-    <!-- Option title for letting user delete data from Google servers.  [CHAR LIMIT=33] -->
-    <string name="clear_sync_data_title">Delete Keyboard Cloud data</string>
-    <!-- Option summary for letting user delete data from Google servers. [CHAR LIMIT=65] -->
+    <!-- Option title for letting user delete synced google keyboard data from Google servers.  [CHAR LIMIT=35] -->
+    <string name="clear_sync_data_title">Delete cloud data</string>
+    <!-- Option summary for letting user delete synced google keyboard data from Google servers. [CHAR LIMIT=65] -->
     <string name="clear_sync_data_summary">Deletes your synced data from Google</string>
     <!-- Text for confirmation dialog box asking user to confirm deletion of cloud data. [CHAR LIMIT=65] -->
     <string name="clear_sync_data_confirmation">Your synced data will be deleted from the cloud. Are you sure?</string>
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 64929ad..0b0c93e 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -366,6 +366,7 @@
     />
     <!-- TODO: This Hinglish keyboard is a preliminary layout.
                This isn't based on the final specification. -->
+    <!--  Disabled because there is no LM yet, and this layout does not offer anything different.
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_hi_ZZ"
             android:subtypeId="0x352eb37c"
@@ -374,6 +375,7 @@
             android:imeSubtypeExtraValue="AsciiCapable,KeyboardLayoutSet=qwerty,EmojiCapable"
             android:isAsciiCapable="true"
     />
+    -->
     <subtype android:icon="@drawable/ic_ime_switcher_dark"
             android:label="@string/subtype_generic"
             android:subtypeId="0x35b7526a"
diff --git a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
index 12fdd69..ee142d8 100644
--- a/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
+++ b/java/src/com/android/inputmethod/dictionarypack/ActionBatch.java
@@ -173,7 +173,7 @@
             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 3d0e29e..3cd822a 100644
--- a/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java
+++ b/java/src/com/android/inputmethod/dictionarypack/CommonPreferences.java
@@ -22,6 +22,8 @@
 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 @@
         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 c678f08..bbdf2a3 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.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 @@
 
     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 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 14e0050..88ea4e6 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.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 @@
 
     @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 @@
         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 @@
     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 b00a811..a2789cc 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -264,6 +264,8 @@
      */
     @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 f05db9d..30ff0b8 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -449,6 +449,8 @@
         // 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 @@
                     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 @@
             } 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 @@
                     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 @@
         // 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 @@
                 || 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 @@
                     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 6b49f9a..d5dff10 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 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 @@
 
     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 e5d770a..9ce92da 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
@@ -19,7 +19,6 @@
 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.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 @@
     }
 
     @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 5dd39d3..a6b37aa 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 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 80daedd..1ef7061 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -646,16 +646,6 @@
         });
     }
 
-    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 @@
         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 5c3abd2..2a69d36 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.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 @@
             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 @@
         }
     }
 
+    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 f7c5f67..62834cd 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 @@
  */
 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 @@
         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 @@
         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 @@
         }
     }
 
-    @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 dee4811..9975277 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 @@
         }
         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 b98c53a..f5455e3 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 @@
 
     @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 fd567f4..d8e3323 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.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.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 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 @@
             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 @@
      * @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 @@
         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 @@
             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 1bd8f31..0000000
--- 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;
-    }
-}
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
index 3a8d19d..87f2f30 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/KeyboardLayoutSetSubtypesCountTests.java
@@ -27,8 +27,8 @@
 
 @SmallTest
 public class KeyboardLayoutSetSubtypesCountTests extends KeyboardLayoutSetTestsBase {
-    private static final int NUMBER_OF_SUBTYPES = 82;
-    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 50;
+    private static final int NUMBER_OF_SUBTYPES = 81;
+    private static final int NUMBER_OF_ASCII_CAPABLE_SUBTYPES = 49;
     private static final int NUMBER_OF_PREDEFINED_ADDITIONAL_SUBTYPES = 2;
 
     @Override
diff --git a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
index 613b3bb..a8e8723 100644
--- a/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
+++ b/tests/src/com/android/inputmethod/keyboard/layout/tests/TestsHinglish.java
@@ -16,7 +16,7 @@
 
 package com.android.inputmethod.keyboard.layout.tests;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
 
 import com.android.inputmethod.keyboard.layout.LayoutBase;
 import com.android.inputmethod.keyboard.layout.Qwerty;
@@ -30,7 +30,7 @@
 /*
  * hi_ZZ: Hinglish/qwerty
  */
-@SmallTest
+@Suppress
 public final class TestsHinglish extends LayoutTestsBase {
     private static final Locale LOCALE = new Locale("hi", "ZZ");
     private static final LayoutBase LAYOUT = new Qwerty(new HinglishCustomizer(LOCALE));
diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
index e92831c..e96c934 100644
--- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
+++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryTests.java
@@ -44,10 +44,6 @@
     private static final String TEST_LOCALE = "test";
     private static final String DICTIONARY_ID = "TestBinaryDictionary";
 
-    private static boolean supportsNgram(final int formatVersion) {
-        return formatVersion >= FormatSpec.VERSION403;
-    }
-
     private HashSet<File> mDictFilesToBeDeleted = new HashSet<>();
 
     @Override
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
index f2885f5..02cd21c 100644
--- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -645,22 +645,6 @@
                 mEditText.getText().toString());
     }
 
-    public void testSwitchLanguages() {
-        final String WORD_TO_TYPE_FIRST_PART = "com";
-        final String WORD_TO_TYPE_SECOND_PART = "md";
-        final String EXPECTED_RESULT = "comme";
-        changeLanguage("en");
-        type(WORD_TO_TYPE_FIRST_PART);
-        changeLanguage("fr");
-        runMessages();
-        type(WORD_TO_TYPE_SECOND_PART);
-        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
-        runMessages();
-        final SuggestedWords suggestedWords = mLatinIME.getSuggestedWordsForTest();
-        assertEquals("Suggestions updated after switching languages",
-                    EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(1) : null);
-    }
-
     public void testBasicGesture() {
         gesture("this");
         assertEquals("this", mEditText.getText().toString());
@@ -743,18 +727,10 @@
         type(" ");
         typeWordAndPutCursorInside(WORD_TO_TYPE, cursorPos + 1 /* startPos */);
         type(Constants.CODE_DELETE);
+        sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         ensureComposingSpanPos("delete while in the middle of a word cancels composition", -1, -1);
     }
 
-    public void testAutoCorrectForFrench() {
-        final String STRING_TO_TYPE = "irq ";
-        final String EXPECTED_RESULT = "ir a ";
-        changeLanguage("es");
-        type(STRING_TO_TYPE);
-        assertEquals("simple auto-correct for Spanish", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
     public void testManualPickThenSeparatorForFrench() {
         final String WORD1_TO_TYPE = "test";
         final String WORD2_TO_TYPE = "!";
@@ -780,13 +756,12 @@
                 mEditText.getText().toString());
     }
 
-    public void testWordThenSpaceThenPunctuationFromStripTwiceForFrench() {
+    public void testWordThenSpaceThenPunctuationFromStripTwice() {
         setBooleanPreference(Settings.PREF_BIGRAM_PREDICTIONS, false, true);
 
         final String WORD_TO_TYPE = "test ";
         final String PUNCTUATION_FROM_STRIP = "!";
-        final String EXPECTED_RESULT = "test !!";
-        changeLanguage("fr");
+        final String EXPECTED_RESULT = "test!! ";
         type(WORD_TO_TYPE);
         sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
@@ -794,14 +769,12 @@
                 mLatinIME.getSuggestedWordsForTest().isPunctuationSuggestions());
         pickSuggestionManually(PUNCTUATION_FROM_STRIP);
         pickSuggestionManually(PUNCTUATION_FROM_STRIP);
-        assertEquals("type word then type space then punctuation from strip twice for French",
-                EXPECTED_RESULT, mEditText.getText().toString());
+        assertEquals(EXPECTED_RESULT, mEditText.getText().toString());
     }
 
     public void testWordThenSpaceDisplaysPredictions() {
-        final String WORD_TO_TYPE = "beaujolais ";
-        final String EXPECTED_RESULT = "nouveau";
-        changeLanguage("fr");
+        final String WORD_TO_TYPE = "Barack ";
+        final String EXPECTED_RESULT = "Obama";
         type(WORD_TO_TYPE);
         sleep(DELAY_TO_WAIT_FOR_UNDERLINE_MILLIS);
         runMessages();
@@ -809,22 +782,4 @@
         assertEquals("type word then type space yields predictions for French",
                 EXPECTED_RESULT, suggestedWords.size() > 0 ? suggestedWords.getWord(0) : null);
     }
-
-    public void testAutoCorrectForGerman() {
-        final String STRING_TO_TYPE = "unf ";
-        final String EXPECTED_RESULT = "und ";
-        changeLanguage("de");
-        type(STRING_TO_TYPE);
-        assertEquals("simple auto-correct for German", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
-
-    public void testAutoCorrectWithUmlautForGerman() {
-        final String STRING_TO_TYPE = "ueber ";
-        final String EXPECTED_RESULT = "über ";
-        changeLanguage("de");
-        type(STRING_TO_TYPE);
-        assertEquals("auto-correct with umlaut for German", EXPECTED_RESULT,
-                mEditText.getText().toString());
-    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 0d9b36a..dead53d 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -66,7 +66,8 @@
     protected static final int DELAY_TO_WAIT_FOR_PREDICTIONS_MILLIS = 200;
     // We wait for gesture computation for this delay
     protected static final int DELAY_TO_WAIT_FOR_GESTURE_MILLIS = 200;
-    private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 60;
+    // If a dictionary takes longer to load, we could have serious problems.
+    private final int TIMEOUT_TO_WAIT_FOR_LOADING_MAIN_DICTIONARY_IN_SECONDS = 5;
 
     // Type for a test phony dictionary
     private static final String TYPE_TEST = "test";
@@ -106,12 +107,15 @@
                 throw new RuntimeException("Expected one span, found " + spans.length);
             }
         }
+        public SuggestionSpan getSpan() {
+            return (SuggestionSpan) mSpan;
+        }
         public boolean isAutoCorrectionIndicator() {
             return (mSpan instanceof SuggestionSpan) &&
-                    0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & ((SuggestionSpan)mSpan).getFlags());
+                    0 != (SuggestionSpan.FLAG_AUTO_CORRECTION & getSpan().getFlags());
         }
         public String[] getSuggestions() {
-            return ((SuggestionSpan)mSpan).getSuggestions();
+            return getSpan().getSuggestions();
         }
     }
 
@@ -152,8 +156,6 @@
         super(LatinIMEForTests.class);
     }
 
-    // TODO: Isn't there a way to make this generic somehow? We can take a <T> and return a <T>
-    // but we'd have to dispatch types on editor.put...() functions
     protected boolean setBooleanPreference(final String key, final boolean value,
             final boolean defaultValue) {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
index 0878e74..7a019c3 100644
--- a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -85,7 +85,7 @@
     }
 
     public void testMultipleAccounts_noSettingsForManagedProfile() {
-        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(true);
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(true);
 
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
@@ -97,7 +97,7 @@
     }
 
     public void testMultipleAccounts_noCurrentAccount() {
-        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(false);
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
 
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
@@ -118,7 +118,7 @@
     }
 
     public void testMultipleAccounts_currentAccount() {
-        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(false);
+        when(mManagedProfileUtils.hasWorkProfile(any(Context.class))).thenReturn(false);
 
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
diff --git a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
index 2272d6b..e7c48da 100644
--- a/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
+++ b/tests/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerServiceTest.java
@@ -53,14 +53,8 @@
         sleep(1000);
 
         final SpanGetter span = new SpanGetter(mEditText.getText(), SuggestionSpan.class);
-        // If no span, the following will crash
-        final String[] suggestions = span.getSuggestions();
-        // For this test we consider "годп" should yield at least 2 suggestions (at this moment
-        // it yields 5).
-        assertTrue(suggestions.length >= 2);
-        // We also assume the top suggestion should be "года", which is the top word in the
-        // Russian dictionary.
-        assertEquals("", "года", suggestions[0]);
+        // We don't ship with Russian LM
+        assertNull(span.getSpan());
     }
 
     public void testSpellcheckWithPeriods() {