From a0a7a7440e860c61c8261c5009dbe351869896b3 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Tue, 22 Apr 2014 09:23:19 -0400 Subject: [PATCH] Add synchronization to DeferredBindRunnables Seems that on occasion the list is being iterated on while being modified. To fix this added synchronization to all modifications to the list as well as iterating on a copy of the list to cut down on time holding the lock. Bug: 12885709 Change-Id: I4287bdedbeb8e438b49c1f79b44819a752c28a69 --- src/com/android/launcher3/LauncherModel.java | 33 +++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index e5eca625b..0efd1728f 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -498,7 +498,9 @@ public class LauncherModel extends BroadcastReceiver { } // Clear any deferred bind runnables - mDeferredBindRunnables.clear(); + synchronized (mDeferredBindRunnables) { + mDeferredBindRunnables.clear(); + } // Remove any queued bind runnables mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE); // Unbind all the workspace items @@ -1315,7 +1317,9 @@ public class LauncherModel extends BroadcastReceiver { // Clear any deferred bind-runnables from the synchronized load process // We must do this before any loading/binding is scheduled below. - mDeferredBindRunnables.clear(); + synchronized (mDeferredBindRunnables) { + mDeferredBindRunnables.clear(); + } // Don't bother to start the thread if we know it's not going to do anything if (mCallbacks != null && mCallbacks.get() != null) { @@ -1337,10 +1341,15 @@ public class LauncherModel extends BroadcastReceiver { void bindRemainingSynchronousPages() { // Post the remaining side pages to be loaded if (!mDeferredBindRunnables.isEmpty()) { - for (final Runnable r : mDeferredBindRunnables) { + Runnable[] deferredBindRunnables = null; + synchronized (mDeferredBindRunnables) { + deferredBindRunnables = mDeferredBindRunnables.toArray( + new Runnable[mDeferredBindRunnables.size()]); + mDeferredBindRunnables.clear(); + } + for (final Runnable r : deferredBindRunnables) { mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE); } - mDeferredBindRunnables.clear(); } } @@ -2367,7 +2376,9 @@ public class LauncherModel extends BroadcastReceiver { } }; if (postOnMainThread) { - deferredBindRunnables.add(r); + synchronized (deferredBindRunnables) { + deferredBindRunnables.add(r); + } } else { runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE); } @@ -2384,7 +2395,9 @@ public class LauncherModel extends BroadcastReceiver { } }; if (postOnMainThread) { - deferredBindRunnables.add(r); + synchronized (deferredBindRunnables) { + deferredBindRunnables.add(r); + } } else { runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE); } @@ -2506,7 +2519,9 @@ public class LauncherModel extends BroadcastReceiver { // Load all the remaining pages (if we are loading synchronously, we want to defer this // work until after the first render) - mDeferredBindRunnables.clear(); + synchronized (mDeferredBindRunnables) { + mDeferredBindRunnables.clear(); + } bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders, (isLoadingSynchronously ? mDeferredBindRunnables : null)); @@ -2528,7 +2543,9 @@ public class LauncherModel extends BroadcastReceiver { } }; if (isLoadingSynchronously) { - mDeferredBindRunnables.add(r); + synchronized (mDeferredBindRunnables) { + mDeferredBindRunnables.add(r); + } } else { runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE); } -- 2.11.0