Upgrade calllog DB to use ICC ID & source_phone_number.

To accomodate backup and restore of the call log, we have to convert the
existing sub-ID to an ICC ID.  Also, add the source_phone_number to the
list of call log columns.

The ICC ID improves backup and restore because it is persistent across
different devices where a sub ID is not.  If the user completely changes
their SIM card, the source_phone_number will be helpful in identifying
that scenario if the user kept their old phone.

Change-Id: Ib35e25216691e580b5ea539929ff16b2e3d30b88
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index d4339b0..6bf913e 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -108,6 +108,7 @@
         sCallsProjectionMap.put(Calls.FEATURES, Calls.FEATURES);
         sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_COMPONENT_NAME, Calls.PHONE_ACCOUNT_COMPONENT_NAME);
         sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ID, Calls.PHONE_ACCOUNT_ID);
+        sCallsProjectionMap.put(Calls.PHONE_ACCOUNT_ADDRESS, Calls.PHONE_ACCOUNT_ADDRESS);
         sCallsProjectionMap.put(Calls.NEW, Calls.NEW);
         sCallsProjectionMap.put(Calls.VOICEMAIL_URI, Calls.VOICEMAIL_URI);
         sCallsProjectionMap.put(Calls.TRANSCRIPTION, Calls.TRANSCRIPTION);
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index e4688ee..fc4d343 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.providers.contacts;
 
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
@@ -73,6 +74,8 @@
 import android.provider.VoicemailContract;
 import android.provider.VoicemailContract.Voicemails;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.text.util.Rfc822Token;
 import android.text.util.Rfc822Tokenizer;
@@ -84,7 +87,6 @@
 import com.android.providers.contacts.database.DeletedContactsTableUtil;
 import com.android.providers.contacts.database.MoreDatabaseUtils;
 import com.android.providers.contacts.util.NeededForTesting;
-
 import com.google.android.collect.Sets;
 import com.google.common.annotations.VisibleForTesting;
 
@@ -119,7 +121,7 @@
      *   1000-1100 M
      * </pre>
      */
-    static final int DATABASE_VERSION = 1002;
+    static final int DATABASE_VERSION = 1003;
 
     public interface Tables {
         public static final String CONTACTS = "contacts";
@@ -1516,6 +1518,7 @@
                 Calls.FEATURES + " INTEGER NOT NULL DEFAULT 0," +
                 Calls.PHONE_ACCOUNT_COMPONENT_NAME + " TEXT," +
                 Calls.PHONE_ACCOUNT_ID + " TEXT," +
+                Calls.PHONE_ACCOUNT_ADDRESS + " TEXT," +
                 Calls.SUB_ID + " INTEGER DEFAULT -1," +
                 Calls.NEW + " INTEGER," +
                 Calls.CACHED_NAME + " TEXT," +
@@ -2873,6 +2876,11 @@
             oldVersion = 1002;
         }
 
+        if (oldVersion < 1003) {
+            upgradeToVersion1003(db);
+            oldVersion = 1003;
+        }
+
         if (upgradeViewsAndTriggers) {
             createContactsViews(db);
             createGroupsView(db);
@@ -4335,6 +4343,37 @@
                 "expiration INTEGER NOT NULL DEFAULT 0);");
     }
 
+    public void upgradeToVersion1003(SQLiteDatabase db) {
+        db.execSQL("ALTER TABLE calls ADD phone_account_address TEXT;");
+
+        // After version 1003, we are using the ICC ID as the phone-account ID. This code updates
+        // any existing telephony connection-service calllog entries to the ICC ID from the
+        // previously used subscription ID.
+        // TODO: This is inconsistent, depending on the initialization state of SubscriptionManager.
+        //       Sometimes it returns zero subscriptions. May want to move this upgrade to run after
+        //       ON_BOOT_COMPLETE instead of PRE_BOOT_COMPLETE.
+        SubscriptionManager sm = SubscriptionManager.from(mContext);
+        if (sm != null) {
+            Log.i(TAG, "count: " + sm.getAllSubscriptionInfoCount());
+            for (SubscriptionInfo info : sm.getAllSubscriptionInfoList()) {
+                String iccId = info.getIccId();
+                int subId = info.getSubscriptionId();
+                if (!TextUtils.isEmpty(iccId) &&
+                        subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("UPDATE calls SET subscription_id=");
+                    DatabaseUtils.appendEscapedSQLString(sb, iccId);
+                    sb.append(" WHERE subscription_id=");
+                    sb.append(subId);
+                    sb.append(" AND subscription_component_name='com.android.phone/"
+                            + "com.android.services.telephony.TelephonyConnectionService';");
+
+                    db.execSQL(sb.toString());
+                }
+            }
+        }
+    }
+
     public String extractHandleFromEmailAddress(String email) {
         Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(email);
         if (tokens.length == 0) {
diff --git a/tests/src/com/android/providers/contacts/CallLogProviderTest.java b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
index d879dd9..b8233f6 100644
--- a/tests/src/com/android/providers/contacts/CallLogProviderTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogProviderTest.java
@@ -62,7 +62,7 @@
             Voicemails.SOURCE_DATA,
             Voicemails.STATE};
     /** Total number of columns exposed by call_log provider. */
-    private static final int NUM_CALLLOG_FIELDS = 24;
+    private static final int NUM_CALLLOG_FIELDS = 25;
 
     private CallLogProvider mCallLogProvider;