Prevent wakelock from being held when sync services finish

* Make sure that ExchangeService#done is called when all threads
  exit
* Make ExchangeService#done ensure that the calling thread is
  still the active syncing thread for its mailbox before taking
  action
* For MR0/MR1

Bug: 5256268
Change-Id: I64bc5f2539c524f3b8d633117ca1c548a373e449
diff --git a/src/com/android/exchange/EasSyncService.java b/src/com/android/exchange/EasSyncService.java
index 7132fdd..a1f3a58 100644
--- a/src/com/android/exchange/EasSyncService.java
+++ b/src/com/android/exchange/EasSyncService.java
@@ -2477,10 +2477,9 @@
                 userLog("Uncaught exception in EasSyncService", e);
             } finally {
                 int status;
-
+                ExchangeService.done(this);
                 if (!mStop) {
                     userLog("Sync finished");
-                    ExchangeService.done(this);
                     switch (mExitStatus) {
                         case EXIT_IO_ERROR:
                             status = EmailServiceStatus.CONNECTION_ERROR;
diff --git a/src/com/android/exchange/ExchangeService.java b/src/com/android/exchange/ExchangeService.java
index 153b7ed..d6d0a03 100644
--- a/src/com/android/exchange/ExchangeService.java
+++ b/src/com/android/exchange/ExchangeService.java
@@ -2075,6 +2075,12 @@
         }
     }
 
+    /**
+     * Release a mailbox from the service map and release its wake lock.
+     * NOTE: This method MUST be called while holding sSyncLock!
+     *
+     * @param mailboxId the id of the mailbox to be released
+     */
     private void releaseMailbox(long mailboxId) {
         mServiceMap.remove(mailboxId);
         releaseWakeLock(mailboxId);
@@ -2521,6 +2527,13 @@
         }
     }
 
+    private boolean isRunningInServiceThread(long mailboxId) {
+        AbstractSyncService syncService = mServiceMap.get(mailboxId);
+        Thread thisThread = Thread.currentThread();
+        return syncService != null && syncService.mThread != null &&
+            thisThread == syncService.mThread;
+    }
+
     /**
      * Sent by services indicating that their thread is finished; action depends on the exitStatus
      * of the service.
@@ -2532,9 +2545,15 @@
         if (exchangeService == null) return;
         synchronized(sSyncLock) {
             long mailboxId = svc.mMailboxId;
+            // If we're no longer the syncing thread for the mailbox, just return
+            if (!exchangeService.isRunningInServiceThread(mailboxId)) {
+                return;
+            }
+            exchangeService.releaseMailbox(mailboxId);
+
             ConcurrentHashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap;
             SyncError syncError = errorMap.get(mailboxId);
-            exchangeService.releaseMailbox(mailboxId);
+
             int exitStatus = svc.mExitStatus;
             Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
             if (m == null) return;