diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index 78d13ebf9982acbdb3df853caff769ea1a1c6bee..7d01351b44f7ee8f2504ed71a3d99370787c1234 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -50,7 +50,7 @@ public class MetadataDbHelper extends SQLiteOpenHelper {
     private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
     // The current database version.
     // This MUST be increased every time the dictionary pack metadata URL changes.
-    private static final int CURRENT_METADATA_DATABASE_VERSION = 15;
+    private static final int CURRENT_METADATA_DATABASE_VERSION = 16;
 
     private final static long NOT_A_DOWNLOAD_ID = -1;
 
diff --git a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
index d1e3c91dd4632c0391c2257ca8c66150f0fcdea1..93725729c8112361bfb1ddf830681cbe2c0e150d 100644
--- a/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/UpdateHandler.java
@@ -221,7 +221,7 @@ public final class UpdateHandler {
      */
     private static void updateClientsWithMetadataUri(
             final Context context, final String metadataUri) {
-        PrivateLog.log("Update for metadata URI " + DebugLogUtils.s(metadataUri));
+        Log.i(TAG, "updateClientsWithMetadataUri() : MetadataUri = " + metadataUri);
         // Adding a disambiguator to circumvent a bug in older versions of DownloadManager.
         // DownloadManager also stupidly cuts the extension to replace with its own that it
         // gets from the content-type. We need to circumvent this.
@@ -255,7 +255,7 @@ public final class UpdateHandler {
             // method will ignore it.
             writeMetadataDownloadId(context, metadataUri, downloadId);
         }
-        PrivateLog.log("Requested download with id " + downloadId);
+        Log.i(TAG, "updateClientsWithMetadataUri() : DownloadId = " + downloadId);
     }
 
     /**
@@ -327,11 +327,11 @@ public final class UpdateHandler {
      */
     public static long registerDownloadRequest(final DownloadManagerWrapper manager,
             final Request request, final SQLiteDatabase db, final String id, final int version) {
-        DebugLogUtils.l("RegisterDownloadRequest for word list id : ", id, ", version ", version);
+        Log.i(TAG, "registerDownloadRequest() : Id = " + id + " : Version = " + version);
         final long downloadId;
         synchronized (sSharedIdProtector) {
             downloadId = manager.enqueue(request);
-            DebugLogUtils.l("Download requested with id", downloadId);
+            Log.i(TAG, "registerDownloadRequest() : DownloadId = " + downloadId);
             MetadataDbHelper.markEntryAsDownloading(db, id, version, downloadId);
         }
         return downloadId;
@@ -582,7 +582,7 @@ public final class UpdateHandler {
      * @throws BadFormatException if the metadata is not in a known format.
      * @throws IOException if the downloaded file can't be read from the disk
      */
-    private static void handleMetadata(final Context context, final InputStream stream,
+    public static void handleMetadata(final Context context, final InputStream stream,
             final String clientId) throws IOException, BadFormatException {
         DebugLogUtils.l("Entering handleMetadata");
         final List<WordListMetadata> newMetadata;
@@ -905,6 +905,8 @@ public final class UpdateHandler {
     // word list ID / client ID combination.
     public static void installIfNeverRequested(final Context context, final String clientId,
             final String wordlistId, final boolean mayPrompt) {
+        Log.i(TAG, "installIfNeverRequested() : ClientId = " + clientId
+                + " : WordListId = " + wordlistId + " : MayPrompt = " + mayPrompt);
         final String[] idArray = wordlistId.split(DictionaryProvider.ID_CATEGORY_SEPARATOR);
         // If we have a new-format dictionary id (category:manual_id), then use the
         // specified category. Otherwise, it is a main dictionary, so force the
@@ -959,8 +961,8 @@ 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)));
+        WordListMetadata metadata = WordListMetadata.createFromContentValues(installCandidate);
+        actions.add(new ActionBatch.StartDownloadAction(clientId, metadata));
         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
@@ -972,6 +974,7 @@ public final class UpdateHandler {
             intent.putExtra(DictionaryService.LOCALE_INTENT_ARGUMENT, localeString);
             context.startService(intent);
         }
+        Log.i(TAG, "installIfNeverRequested() : StartDownloadAction for " + metadata);
         actions.execute(context, new LogProblemReporter(TAG));
     }
 
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index afedde0025b30009fae09bb97b78bc83ae7f686d..d25c1d3734de4a96baf4271ff9e46782ba16d2ee 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -29,6 +29,7 @@ import android.util.Log;
 
 import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
 import com.android.inputmethod.dictionarypack.MD5Calculator;
+import com.android.inputmethod.dictionarypack.UpdateHandler;
 import com.android.inputmethod.latin.common.FileUtils;
 import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
@@ -487,6 +488,8 @@ public final class BinaryDictionaryFileDumper {
     private static void reinitializeClientRecordInDictionaryContentProvider(final Context context,
             final ContentProviderClient client, final String clientId) throws RemoteException {
         final String metadataFileUri = MetadataFileUriGetter.getMetadataUri(context);
+        Log.i(TAG, "reinitializeClientRecordInDictionaryContentProvider() : MetadataFileUri = "
+                + metadataFileUri);
         final String metadataAdditionalId = MetadataFileUriGetter.getMetadataAdditionalId(context);
         // Tell the content provider to reset all information about this client id
         final Uri metadataContentUri = getProviderUriBuilder(clientId)
@@ -511,9 +514,34 @@ public final class BinaryDictionaryFileDumper {
         final int length = dictionaryList.size();
         for (int i = 0; i < length; ++i) {
             final DictionaryInfo info = dictionaryList.get(i);
+            Log.i(TAG, "reinitializeClientRecordInDictionaryContentProvider() : Insert " + info);
             client.insert(Uri.withAppendedPath(dictionaryContentUriBase, info.mId),
                     info.toContentValues());
         }
+
+        // Read from metadata file in resources to get the baseline dictionary info.
+        // This ensures we start with a sane list of available dictionaries.
+        final int metadataResourceId = context.getResources().getIdentifier("metadata",
+                "raw", DictionaryInfoUtils.RESOURCE_PACKAGE_NAME);
+        if (metadataResourceId == 0) {
+            Log.w(TAG, "Missing metadata.json resource");
+            return;
+        }
+        InputStream inputStream = null;
+        try {
+            inputStream = context.getResources().openRawResource(metadataResourceId);
+            UpdateHandler.handleMetadata(context, inputStream, clientId);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to read metadata.json from resources", e);
+        } finally {
+            if (inputStream != null) {
+                try {
+                    inputStream.close();
+                } catch (IOException e) {
+                    Log.w(TAG, "Failed to close metadata.json", e);
+                }
+            }
+        }
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index 096a545e5369b063d85c6b80b880ea16f3d22c59..11cccd5faf145587ac8e0f6ce19bffda69a55945 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -54,7 +54,7 @@ import javax.annotation.Nullable;
  */
 public class DictionaryInfoUtils {
     private static final String TAG = DictionaryInfoUtils.class.getSimpleName();
-    private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
+    public static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
     private static final String DEFAULT_MAIN_DICT = "main";
     private static final String MAIN_DICT_PREFIX = "main_";
     private static final String DECODER_DICT_SUFFIX = DecoderSpecificConstants.DECODER_DICT_SUFFIX;
@@ -103,6 +103,13 @@ public class DictionaryInfoUtils {
             values.put(VERSION_COLUMN, mVersion);
             return values;
         }
+
+        @Override
+        public String toString() {
+            return "DictionaryInfo : Id = '" + mId
+                    + "' : Locale=" + mLocale
+                    + " : Version=" + mVersion;
+        }
     }
 
     private DictionaryInfoUtils() {