Add locking when mutating RecentTasks.

Otherwise there is a really rare race condition where we try tearing
down the tasks while we're still setting them up.

Bug: 25078914
Change-Id: Icf89241f9abec3fadc8606cfb4fbc029bbe91515
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index f5908c5..407838a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -36,6 +36,7 @@
 
 import com.android.documentsui.BaseActivity.State;
 import com.android.documentsui.model.RootInfo;
+import com.android.internal.annotations.GuardedBy;
 import com.google.android.collect.Maps;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.AbstractFuture;
@@ -81,6 +82,7 @@
     private final RootsCache mRoots;
     private final State mState;
 
+    @GuardedBy("mTasks")
     private final HashMap<RootInfo, RecentTask> mTasks = Maps.newHashMap();
 
     private final int mSortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -167,6 +169,12 @@
 
     @Override
     public DirectoryResult loadInBackground() {
+        synchronized (mTasks) {
+            return loadInBackgroundLocked();
+        }
+    }
+
+    private DirectoryResult loadInBackgroundLocked() {
         if (mFirstPassLatch == null) {
             // First time through we kick off all the recent tasks, and wait
             // around to see if everyone finishes quickly.
@@ -304,8 +312,10 @@
         // Ensure the loader is stopped
         onStopLoading();
 
-        for (RecentTask task : mTasks.values()) {
-            IoUtils.closeQuietly(task);
+        synchronized (mTasks) {
+            for (RecentTask task : mTasks.values()) {
+                IoUtils.closeQuietly(task);
+            }
         }
 
         IoUtils.closeQuietly(mResult);