Do alert work in background thread

* An ANR was reported in MailboxAlarmReceiver
* The reciever calls into SyncManager, which does some database
  operations, and may abort an I/O operation in a sync service
  thread
* Move this potentially long-running code into a background
  thread

Bug: 2215045
Change-Id: Id65c51f706b212d6b50af3921f3ba3dc2d014ce0
diff --git a/src/com/android/exchange/SyncManager.java b/src/com/android/exchange/SyncManager.java
index dae467e..57284ce 100644
--- a/src/com/android/exchange/SyncManager.java
+++ b/src/com/android/exchange/SyncManager.java
@@ -1321,31 +1321,38 @@
         }
     }
 
-    static public void alert(Context context, long id) {
-        SyncManager syncManager = INSTANCE;
+    static public void alert(Context context, final long id) {
+        final SyncManager syncManager = INSTANCE;
         checkSyncManagerServiceRunning();
         if (id < 0) {
             kick("ping SyncManager");
         } else if (syncManager == null) {
             context.startService(new Intent(context, SyncManager.class));
         } else {
-            AbstractSyncService service = syncManager.mServiceMap.get(id);
+            final AbstractSyncService service = syncManager.mServiceMap.get(id);
             if (service != null) {
-                Mailbox m = Mailbox.restoreMailboxWithId(syncManager, id);
-                if (m != null) {
-                    // We ignore drafts completely (doesn't sync).  Changes in Outbox are handled
-                    // in the checkMailboxes loop, so we can ignore these pings.
-                    if (m.mType == Mailbox.TYPE_DRAFTS || m.mType == Mailbox.TYPE_OUTBOX) {
-                        String[] args = new String[] {Long.toString(m.mId)};
-                        ContentResolver resolver = INSTANCE.mResolver;
-                        resolver.delete(Message.DELETED_CONTENT_URI, WHERE_MAILBOX_KEY, args);
-                        resolver.delete(Message.UPDATED_CONTENT_URI, WHERE_MAILBOX_KEY, args);
-                        return;
-                    }
-                    service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
-                    service.mMailbox = m;
-                    service.alarm();
-                }
+                // Handle alerts in a background thread, as we are typically called from a
+                // broadcast receiver, and are therefore running in the UI thread
+                new Thread(new Runnable() {
+                   public void run() {
+                       Mailbox m = Mailbox.restoreMailboxWithId(syncManager, id);
+                       if (m != null) {
+                           // We ignore drafts completely (doesn't sync).  Changes in Outbox are
+                           // handled in the checkMailboxes loop, so we can ignore these pings.
+                           if (m.mType == Mailbox.TYPE_DRAFTS || m.mType == Mailbox.TYPE_OUTBOX) {
+                               String[] args = new String[] {Long.toString(m.mId)};
+                               ContentResolver resolver = INSTANCE.mResolver;
+                               resolver.delete(Message.DELETED_CONTENT_URI, WHERE_MAILBOX_KEY,
+                                       args);
+                               resolver.delete(Message.UPDATED_CONTENT_URI, WHERE_MAILBOX_KEY,
+                                       args);
+                               return;
+                           }
+                           service.mAccount = Account.restoreAccountWithId(INSTANCE, m.mAccountKey);
+                           service.mMailbox = m;
+                           service.alarm();
+                       }
+                    }}).start();
             }
         }
     }