Deleting a thread will mess up a multi-recipient thread with the same recipient

Bug 5763490
The previous DB query for deleting unreferenced recipient id's didn't work
on threads addressed to multiple recipients because the recipient id's are
stored as a space-separated list of ids in a single column. With this change,
the work for identifying unreferenced recipient id's is done in java,
rather than in an sqlite3 selection statement.

Change-Id: Id6ad32408a67dc7550b32ce8ab095635c324a799
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 62e435a..3ba6e78 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -21,6 +21,8 @@
 import java.io.FileInputStream;
 import java.io.File;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
 
 import android.content.BroadcastReceiver;
 import android.content.ContentValues;
@@ -235,6 +237,51 @@
         return sInstance;
     }
 
+    /**
+     * Look through all the recipientIds referenced by the threads and then delete any
+     * unreferenced rows from the canonical_addresses table.
+     */
+    private static void removeUnferencedCanonicalAddresses(SQLiteDatabase db) {
+        Cursor c = db.query("threads", new String[] { "recipient_ids" },
+                null, null, null, null, null);
+        if (c != null) {
+            try {
+                if (c.getCount() == 0) {
+                    // no threads, delete all addresses
+                    int rows = db.delete("canonical_addresses", null, null);
+                } else {
+                    // Find all the referenced recipient_ids from the threads. recipientIds is
+                    // a space-separated list of recipient ids: "1 14 21"
+                    HashSet<Integer> recipientIds = new HashSet<Integer>();
+                    while (c.moveToNext()) {
+                        String[] recips = c.getString(0).split(" ");
+                        for (String recip : recips) {
+                            try {
+                                int recipientId = Integer.parseInt(recip);
+                                recipientIds.add(recipientId);
+                            } catch (Exception e) {
+                            }
+                        }
+                    }
+                    // Now build a selection string of all the unique recipient ids
+                    StringBuilder sb = new StringBuilder();
+                    Iterator<Integer> iter = recipientIds.iterator();
+                    while (iter.hasNext()) {
+                        sb.append("_id != " + iter.next());
+                        if (iter.hasNext()) {
+                            sb.append(" AND ");
+                        }
+                    }
+                    if (sb.length() > 0) {
+                        int rows = db.delete("canonical_addresses", sb.toString(), null);
+                    }
+                }
+            } finally {
+                c.close();
+            }
+        }
+    }
+
     public static void updateThread(SQLiteDatabase db, long thread_id) {
         if (thread_id < 0) {
             updateAllThreads(db, null, null);
@@ -251,8 +298,7 @@
                   new String[] { String.valueOf(thread_id) });
         if (rows > 0) {
             // If this deleted a row, let's remove orphaned canonical_addresses and get outta here
-            db.delete("canonical_addresses",
-                    "_id NOT IN (SELECT DISTINCT recipient_ids FROM threads)", null);
+            removeUnferencedCanonicalAddresses(db);
             return;
         }
         // Update the message count in the threads table as the sum
@@ -354,8 +400,7 @@
                 "UNION SELECT DISTINCT thread_id FROM pdu)", null);
 
         // remove orphaned canonical_addresses
-        db.delete("canonical_addresses",
-                "_id NOT IN (SELECT DISTINCT recipient_ids FROM threads)", null);
+        removeUnferencedCanonicalAddresses(db);
     }
 
     public static int deleteOneSms(SQLiteDatabase db, int message_id) {