Add an additional ID to the client info.

Bug: 8651863
Change-Id: I748f35726d72ede926d5b06ed87ff029317f1ac3
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
index cb8e25e..03ed267 100644
--- a/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataDbHelper.java
@@ -45,16 +45,16 @@
     private static final int METADATA_DATABASE_INITIAL_VERSION = 3;
     // This is the first released version of the database that implements CLIENTID. It is
     // used to identify the versions for upgrades. This should never change going forward.
-    private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 5;
+    private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
     // This is the current database version. It should be updated when the database schema
     // gets updated. It is passed to the framework constructor of SQLiteOpenHelper, so
     // that's what the framework uses to track our database version.
-    private static final int METADATA_DATABASE_VERSION = 5;
+    private static final int METADATA_DATABASE_VERSION = 6;
 
     private final static long NOT_A_DOWNLOAD_ID = -1;
 
     public static final String METADATA_TABLE_NAME = "pendingUpdates";
-    private static final String CLIENT_TABLE_NAME = "clients";
+    static final String CLIENT_TABLE_NAME = "clients";
     public static final String PENDINGID_COLUMN = "pendingid"; // Download Manager ID
     public static final String TYPE_COLUMN = "type";
     public static final String STATUS_COLUMN = "status";
@@ -73,6 +73,7 @@
 
     private static final String CLIENT_CLIENT_ID_COLUMN = "clientid";
     private static final String CLIENT_METADATA_URI_COLUMN = "uri";
+    private static final String CLIENT_METADATA_ADDITIONAL_ID_COLUMN = "additionalid";
     private static final String CLIENT_LAST_UPDATE_DATE_COLUMN = "lastupdate";
     private static final String CLIENT_PENDINGID_COLUMN = "pendingid"; // Download Manager ID
 
@@ -128,6 +129,7 @@
             "CREATE TABLE IF NOT EXISTS " + CLIENT_TABLE_NAME + " ("
             + CLIENT_CLIENT_ID_COLUMN + " TEXT, "
             + CLIENT_METADATA_URI_COLUMN + " TEXT, "
+            + CLIENT_METADATA_ADDITIONAL_ID_COLUMN + " TEXT, "
             + CLIENT_LAST_UPDATE_DATE_COLUMN + " INTEGER NOT NULL DEFAULT 0, "
             + CLIENT_PENDINGID_COLUMN + " INTEGER, "
             + FLAGS_COLUMN + " INTEGER, "
@@ -282,14 +284,15 @@
      * @return the string representation of the URI
      */
     public static String getMetadataUriAsString(final Context context, final String clientId) {
-        SQLiteDatabase defaultDb = getDb(context, null);
-        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
-                new String[] { CLIENT_METADATA_URI_COLUMN },
-                CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId },
+        SQLiteDatabase defaultDb = MetadataDbHelper.getDb(context, null);
+        final Cursor cursor = defaultDb.query(MetadataDbHelper.CLIENT_TABLE_NAME,
+                new String[] { MetadataDbHelper.CLIENT_METADATA_URI_COLUMN,
+                        MetadataDbHelper.CLIENT_METADATA_ADDITIONAL_ID_COLUMN },
+                MetadataDbHelper.CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId },
                 null, null, null, null);
         try {
             if (!cursor.moveToFirst()) return null;
-            return cursor.getString(0); // Only one column, return it
+            return MetadataUriGetter.getUri(context, cursor.getString(0), cursor.getString(1));
         } finally {
             cursor.close();
         }
@@ -298,7 +301,8 @@
     /**
      * Update the last metadata update time for all clients using a particular URI.
      *
-     * All clients using this metadata URI will be indicated as having been updated now.
+     * This method searches for all clients using a particular URI and updates the last
+     * update time for this client.
      * The current time is used as the latest update time. This saved date will be what
      * is returned henceforth by {@link #getLastUpdateDateForClient(Context, String)},
      * until this method is called again.
@@ -311,8 +315,22 @@
         final ContentValues values = new ContentValues();
         values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
         final SQLiteDatabase defaultDb = getDb(context, null);
-        defaultDb.update(CLIENT_TABLE_NAME, values,
-                CLIENT_METADATA_URI_COLUMN + " = ?", new String[] { uri });
+        final Cursor cursor = MetadataDbHelper.queryClientIds(context);
+        if (null == cursor) return;
+        try {
+            if (!cursor.moveToFirst()) return;
+            do {
+                final String clientId = cursor.getString(0);
+                final String metadataUri =
+                        MetadataDbHelper.getMetadataUriAsString(context, clientId);
+                if (metadataUri.equals(uri)) {
+                    defaultDb.update(CLIENT_TABLE_NAME, values,
+                            CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId });
+                }
+            } while (cursor.moveToNext());
+        } finally {
+            cursor.close();
+        }
     }
 
     /**
@@ -727,11 +745,13 @@
     /**
      * Updates information relative to a specific client.
      *
-     * Updatable information includes only the metadata URI, but may be expanded in the future.
+     * Updatable information includes the metadata URI and the additional ID column. It may be
+     * expanded in the future.
      * The passed values must include a client ID in the key CLIENT_CLIENT_ID_COLUMN, and it must
-     * be equal to the string passed as an argument for clientId.
-     * The passed values must also include a non-empty metadata URI in the
-     * CLIENT_METADATA_URI_COLUMN column.
+     * be equal to the string passed as an argument for clientId. It may not be empty.
+     * The passed values must also include a non-null metadata URI in the
+     * CLIENT_METADATA_URI_COLUMN column, as well as a non-null additional ID in the
+     * CLIENT_METADATA_ADDITIONAL_ID_COLUMN. Both these strings may be empty.
      * If any of the above is not complied with, this function returns without updating data.
      *
      * @param context the context, to open the database
@@ -743,10 +763,16 @@
         // Sanity check the content values
         final String valuesClientId = values.getAsString(CLIENT_CLIENT_ID_COLUMN);
         final String valuesMetadataUri = values.getAsString(CLIENT_METADATA_URI_COLUMN);
-        // Empty string is a valid client ID, but external apps may not configure it.
-        // Empty string is a valid metadata URI if the client does not want updates.
-        if (TextUtils.isEmpty(valuesClientId) || null == valuesMetadataUri) {
-            // We need both these columns to be filled in
+        final String valuesMetadataAdditionalId =
+                values.getAsString(CLIENT_METADATA_ADDITIONAL_ID_COLUMN);
+        // Empty string is a valid client ID, but external apps may not configure it, so disallow
+        // both null and empty string.
+        // Empty string is a valid metadata URI if the client does not want updates, so allow
+        // empty string but disallow null.
+        // Empty string is a valid additional ID so allow empty string but disallow null.
+        if (TextUtils.isEmpty(valuesClientId) || null == valuesMetadataUri
+                || null == valuesMetadataAdditionalId) {
+            // We need all these columns to be filled in
             Utils.l("Missing parameter for updateClientInfo");
             return;
         }
@@ -777,8 +803,9 @@
      * Register a download ID for a specific metadata URI.
      *
      * This method should be called when a download for a metadata URI is starting. It will
-     * register the download ID for all clients using this metadata URI into the database
-     * for later retrieval by {@link #getDownloadRecordsForDownloadId(Context, long)}.
+     * search for all clients using this metadata URI and will register for each of them
+     * the download ID into the database for later retrieval by
+     * {@link #getDownloadRecordsForDownloadId(Context, long)}.
      *
      * @param context a context for opening databases
      * @param uri the metadata URI
@@ -789,8 +816,22 @@
         final ContentValues values = new ContentValues();
         values.put(CLIENT_PENDINGID_COLUMN, downloadId);
         final SQLiteDatabase defaultDb = getDb(context, "");
-        defaultDb.update(CLIENT_TABLE_NAME, values,
-                CLIENT_METADATA_URI_COLUMN + " = ?", new String[] { uri });
+        final Cursor cursor = MetadataDbHelper.queryClientIds(context);
+        if (null == cursor) return;
+        try {
+            if (!cursor.moveToFirst()) return;
+            do {
+                final String clientId = cursor.getString(0);
+                final String metadataUri =
+                        MetadataDbHelper.getMetadataUriAsString(context, clientId);
+                if (metadataUri.equals(uri)) {
+                    defaultDb.update(CLIENT_TABLE_NAME, values,
+                            CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId });
+                }
+            } while (cursor.moveToNext());
+        } finally {
+            cursor.close();
+        }
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java b/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
new file mode 100644
index 0000000..ed81765
--- /dev/null
+++ b/java/src/com/android/inputmethod/dictionarypack/MetadataUriGetter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 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.dictionarypack;
+
+import android.content.Context;
+
+/**
+ * Helper to get the metadata URI from its base URI and the additional ID, if any.
+ */
+public class MetadataUriGetter {
+    private MetadataUriGetter() {
+        // This helper class is not instantiable.
+    }
+
+    public static String getUri(final Context context, final String baseUri,
+            final String additionalId) {
+        return baseUri;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 42f7136..4a2c3bb 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -81,6 +81,7 @@
     private static final String QUERY_PATH_METADATA = "metadata";
     private static final String INSERT_METADATA_CLIENT_ID_COLUMN = "clientid";
     private static final String INSERT_METADATA_METADATA_URI_COLUMN = "uri";
+    private static final String INSERT_METADATA_METADATA_ADDITIONAL_ID_COLUMN = "additionalid";
 
     // Prevents this class to be accidentally instantiated.
     private BinaryDictionaryFileDumper() {
@@ -423,6 +424,7 @@
     private static void reinitializeClientRecordInDictionaryContentProvider(final Context context,
             final ContentProviderClient client, final String clientId) throws RemoteException {
         final String metadataFileUri = MetadataFileUriGetter.getMetadataUri(context);
+        final String metadataAdditionalId = MetadataFileUriGetter.getMetadataAdditionalId(context);
         if (TextUtils.isEmpty(metadataFileUri)) return;
         // Tell the content provider to reset all information about this client id
         final Uri metadataContentUri = getProviderUriBuilder(clientId)
@@ -434,6 +436,7 @@
         final ContentValues metadataValues = new ContentValues();
         metadataValues.put(INSERT_METADATA_CLIENT_ID_COLUMN, clientId);
         metadataValues.put(INSERT_METADATA_METADATA_URI_COLUMN, metadataFileUri);
+        metadataValues.put(INSERT_METADATA_METADATA_ADDITIONAL_ID_COLUMN, metadataAdditionalId);
         client.insert(metadataContentUri, metadataValues);
 
         // Update the dictionary list.
diff --git a/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
index e6dc6db..a98ecc7 100644
--- a/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
+++ b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
@@ -19,10 +19,18 @@
 import android.content.Context;
 
 /**
- * Helper class to get the metadata URI.
+ * Helper class to get the metadata URI and the additional ID.
  */
 public class MetadataFileUriGetter {
-    public static String getMetadataUri(Context context) {
+    private MetadataFileUriGetter() {
+        // This helper class is not instantiable.
+    }
+
+    public static String getMetadataUri(final Context context) {
         return context.getString(R.string.dictionary_pack_metadata_uri);
     }
+
+    public static String getMetadataAdditionalId(final Context context) {
+        return "";
+    }
 }