Merge "Separating the config and flags in different directories so that it is easier to override one or the other" into ub-launcher3-master
diff --git a/src/com/android/launcher3/DeferredHandler.java b/src/com/android/launcher3/DeferredHandler.java
deleted file mode 100644
index a43ab67..0000000
--- a/src/com/android/launcher3/DeferredHandler.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.MessageQueue;
-
-import com.android.launcher3.util.Thunk;
-
-import java.util.LinkedList;
-
-/**
- * Queue of things to run on a looper thread. Items posted with {@link #post} will not
- * be actually enqued on the handler until after the last one has run, to keep from
- * starving the thread.
- *
- * This class is fifo.
- */
-public class DeferredHandler {
- @Thunk LinkedList<Runnable> mQueue = new LinkedList<>();
- private MessageQueue mMessageQueue = Looper.myQueue();
- private Impl mHandler = new Impl();
-
- @Thunk class Impl extends Handler implements MessageQueue.IdleHandler {
- public void handleMessage(Message msg) {
- Runnable r;
- synchronized (mQueue) {
- if (mQueue.size() == 0) {
- return;
- }
- r = mQueue.removeFirst();
- }
- r.run();
- synchronized (mQueue) {
- scheduleNextLocked();
- }
- }
-
- public boolean queueIdle() {
- handleMessage(null);
- return false;
- }
- }
-
- private class IdleRunnable implements Runnable {
- Runnable mRunnable;
-
- IdleRunnable(Runnable r) {
- mRunnable = r;
- }
-
- public void run() {
- mRunnable.run();
- }
- }
-
- public DeferredHandler() {
- }
-
- /** Schedule runnable to run after everything that's on the queue right now. */
- public void post(Runnable runnable) {
- synchronized (mQueue) {
- mQueue.add(runnable);
- if (mQueue.size() == 1) {
- scheduleNextLocked();
- }
- }
- }
-
- /** Schedule runnable to run when the queue goes idle. */
- public void postIdle(final Runnable runnable) {
- post(new IdleRunnable(runnable));
- }
-
- public void cancelAll() {
- synchronized (mQueue) {
- mQueue.clear();
- }
- }
-
- /** Runs all queued Runnables from the calling thread. */
- public void flush() {
- LinkedList<Runnable> queue = new LinkedList<>();
- synchronized (mQueue) {
- queue.addAll(mQueue);
- mQueue.clear();
- }
- for (Runnable r : queue) {
- r.run();
- }
- }
-
- void scheduleNextLocked() {
- if (mQueue.size() > 0) {
- Runnable peek = mQueue.getFirst();
- if (peek instanceof IdleRunnable) {
- mMessageQueue.addIdleHandler(mHandler);
- } else {
- mHandler.sendEmptyMessage(1);
- }
- }
- }
-}
-
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 4cc1f64..35811d3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -72,6 +72,7 @@
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
@@ -110,9 +111,9 @@
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
private static final long INVALID_SCREEN_ID = -1L;
+ private final MainThreadExecutor mUiExecutor = new MainThreadExecutor();
@Thunk final LauncherAppState mApp;
@Thunk final Object mLock = new Object();
- @Thunk DeferredHandler mHandler = new DeferredHandler();
@Thunk LoaderTask mLoaderTask;
@Thunk boolean mIsLoaderTaskRunning;
@Thunk boolean mHasLoaderCompletedOnce;
@@ -218,17 +219,6 @@
mUserManager = UserManagerCompat.getInstance(context);
}
- /** Runs the specified runnable immediately if called from the main thread, otherwise it is
- * posted on the main thread handler. */
- private void runOnMainThread(Runnable r) {
- if (sWorkerThread.getThreadId() == Process.myTid()) {
- // If we are on the worker thread, post onto the main handler
- mHandler.post(r);
- } else {
- r.run();
- }
- }
-
/** Runs the specified runnable immediately if called from the worker thread, otherwise it is
* posted on the worker thread handler. */
private static void runOnWorkerThread(Runnable r) {
@@ -378,8 +368,6 @@
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
Preconditions.assertUIThread();
- // Remove any queued UI runnables
- mHandler.cancelAll();
mCallbacks = new WeakReference<>(callbacks);
}
}
@@ -543,11 +531,11 @@
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear any pending bind-runnables from the synchronized load process.
- runOnMainThread(new Runnable() {
- public void run() {
- oldCallbacks.clearPendingBinds();
- }
- });
+ mUiExecutor.execute(new Runnable() {
+ public void run() {
+ oldCallbacks.clearPendingBinds();
+ }
+ });
// If there is already one running, tell it to stop.
stopLoaderLocked();
@@ -598,7 +586,6 @@
@Thunk boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
- @Thunk boolean mLoadAndBindStepFinished;
LoaderTask(Context context, int pageToBindFirst) {
mContext = context;
@@ -610,34 +597,10 @@
// This way we don't start loading all apps until the workspace has settled
// down.
synchronized (LoaderTask.this) {
- final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-
- mHandler.postIdle(new Runnable() {
- public void run() {
- synchronized (LoaderTask.this) {
- mLoadAndBindStepFinished = true;
- if (DEBUG_LOADERS) {
- Log.d(TAG, "done with previous binding step");
- }
- LoaderTask.this.notify();
- }
- }
- });
-
- while (!mStopped && !mLoadAndBindStepFinished) {
- try {
- // Just in case mFlushingWorkerThread changes but we aren't woken up,
- // wait no longer than 1sec at a time
- this.wait(1000);
- } catch (InterruptedException ex) {
- // Ignore
- }
- }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "waited "
- + (SystemClock.uptimeMillis()-workspaceWaitTime)
- + "ms for previous step to finish binding");
- }
+ LooperIdleLock idleLock = new LooperIdleLock(this, Looper.getMainLooper());
+ // Just in case mFlushingWorkerThread changes but we aren't woken up,
+ // wait no longer than 1sec at a time
+ while (!mStopped && idleLock.awaitLocked(1000));
}
}
@@ -660,15 +623,6 @@
}
}
- // XXX: Throw an exception if we are already loading (since we touch the worker thread
- // data structures, we can't allow any other thread to touch that data, but because
- // this call is synchronous, we can get away with not locking).
-
- // The LauncherModel is static in the LauncherAppState and mHandler may have queued
- // operations from the previous activity. We need to ensure that all queued operations
- // are executed before any synchronous binding work is done.
- mHandler.flush();
-
// Divide the set of loaded items into those that we are binding synchronously, and
// everything else that is to be bound normally (asynchronously).
bindWorkspace(synchronousBindPage);
@@ -696,6 +650,7 @@
}
try {
+ long now = 0;
if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
// Set to false in bindWorkspace()
mIsLoadingAndBindingWorkspace = true;
@@ -706,8 +661,12 @@
bindWorkspace(mPageToBindFirst);
// Take a break
- if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle");
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "step 1 completed, wait for idle");
+ now = SystemClock.uptimeMillis();
+ }
waitForIdle();
+ if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms");
verifyNotStopped();
// second step
@@ -719,8 +678,12 @@
updateIconCache();
// Take a break
- if (DEBUG_LOADERS) Log.d(TAG, "step 2 completed, wait for idle");
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "step 2 completed, wait for idle");
+ now = SystemClock.uptimeMillis();
+ }
waitForIdle();
+ if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms");
verifyNotStopped();
// third step
@@ -1433,7 +1396,7 @@
}
}
};
- runOnMainThread(r);
+ mUiExecutor.execute(r);
}
private void bindWorkspaceItems(final Callbacks oldCallbacks,
@@ -1539,11 +1502,11 @@
}
}
};
- runOnMainThread(r);
+ mUiExecutor.execute(r);
bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
- Executor mainExecutor = new DeferredMainThreadExecutor();
+ Executor mainExecutor = mUiExecutor;
// Load items on the current page.
bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets, mainExecutor);
@@ -1553,7 +1516,7 @@
// This ensures that the first screen is immediately visible (eg. during rotation)
// In case of !validFirstPage, bind all pages one after other.
final Executor deferredExecutor =
- validFirstPage ? new ViewOnDrawExecutor(mHandler) : mainExecutor;
+ validFirstPage ? new ViewOnDrawExecutor(mUiExecutor) : mainExecutor;
mainExecutor.execute(new Runnable() {
@Override
@@ -1613,7 +1576,7 @@
}
}
};
- runOnMainThread(r);
+ mUiExecutor.execute(r);
}
}
@@ -1663,7 +1626,7 @@
}
}
};
- runOnMainThread(r);
+ mUiExecutor.execute(r);
}
private void loadAllApps() {
@@ -1711,21 +1674,21 @@
heuristic.processUserApps(apps);
}
};
- runOnMainThread(new Runnable() {
+ mUiExecutor.execute(new Runnable() {
- @Override
- public void run() {
- // Check isLoadingWorkspace on the UI thread, as it is updated on
- // the UI thread.
- if (mIsLoadingAndBindingWorkspace) {
- synchronized (mBindCompleteRunnables) {
- mBindCompleteRunnables.add(r);
- }
- } else {
- runOnWorkerThread(r);
- }
- }
- });
+ @Override
+ public void run() {
+ // Check isLoadingWorkspace on the UI thread, as it is updated on
+ // the UI thread.
+ if (mIsLoadingAndBindingWorkspace) {
+ synchronized (mBindCompleteRunnables) {
+ mBindCompleteRunnables.add(r);
+ }
+ } else {
+ runOnWorkerThread(r);
+ }
+ }
+ });
}
}
// Huh? Shouldn't this be inside the Runnable below?
@@ -1733,7 +1696,7 @@
mBgAllAppsList.added = new ArrayList<AppInfo>();
// Post callback on main thread
- mHandler.post(new Runnable() {
+ mUiExecutor.execute(new Runnable() {
public void run() {
final long bindTime = SystemClock.uptimeMillis();
@@ -1787,7 +1750,7 @@
}
}
};
- runOnMainThread(r);
+ mUiExecutor.execute(r);
}
/**
@@ -1838,12 +1801,12 @@
public static abstract class BaseModelUpdateTask implements Runnable {
private LauncherModel mModel;
- private DeferredHandler mUiHandler;
+ private Executor mUiExecutor;
/* package private */
void init(LauncherModel model) {
mModel = model;
- mUiHandler = mModel.mHandler;
+ mUiExecutor = mModel.mUiExecutor;
}
@Override
@@ -1866,7 +1829,7 @@
*/
public final void scheduleCallbackTask(final CallbackTask task) {
final Callbacks callbacks = mModel.getCallback();
- mUiHandler.post(new Runnable() {
+ mUiExecutor.execute(new Runnable() {
public void run() {
Callbacks cb = mModel.getCallback();
if (callbacks == cb && cb != null) {
@@ -1911,7 +1874,7 @@
private void bindWidgetsModel(final Callbacks callbacks) {
final MultiHashMap<PackageItemInfo, WidgetItem> widgets
= mBgWidgetsModel.getWidgetsMap().clone();
- mHandler.post(new Runnable() {
+ mUiExecutor.execute(new Runnable() {
@Override
public void run() {
Callbacks cb = getCallback();
@@ -1968,14 +1931,6 @@
}
}
- @Thunk class DeferredMainThreadExecutor implements Executor {
-
- @Override
- public void execute(Runnable command) {
- runOnMainThread(command);
- }
- }
-
/**
* @return the looper for the worker thread which can be used to start background tasks.
*/
diff --git a/src/com/android/launcher3/MainThreadExecutor.java b/src/com/android/launcher3/MainThreadExecutor.java
index 4ca0a59..5094682 100644
--- a/src/com/android/launcher3/MainThreadExecutor.java
+++ b/src/com/android/launcher3/MainThreadExecutor.java
@@ -18,14 +18,14 @@
import android.os.Looper;
-import com.android.launcher3.util.LooperExecuter;
+import com.android.launcher3.util.LooperExecutor;
/**
* An executor service that executes its tasks on the main thread.
*
* Shutting down this executor is not supported.
*/
-public class MainThreadExecutor extends LooperExecuter {
+public class MainThreadExecutor extends LooperExecutor {
public MainThreadExecutor() {
super(Looper.getMainLooper());
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index fe8f0ce..15bdea9 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -770,10 +770,14 @@
}
mDragController.removeDropTarget(this);
clearFocus();
- if (wasAnimated) {
- mFolderIcon.requestFocus();
+ if (mFolderIcon != null) {
+ mFolderIcon.setVisibility(View.VISIBLE);
+ if (wasAnimated) {
+ mFolderIcon.requestFocus();
+ }
}
+
if (mRearrangeOnClose) {
rearrangeChildren();
mRearrangeOnClose = false;
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index d14bb40..9ce1c57 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -135,12 +135,6 @@
public AnimatorSet getClosingAnimator() {
AnimatorSet a = getAnimatorSet(false /* isOpening */);
a.setInterpolator(mClosingInterpolator);
- a.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mFolderIcon.setVisibility(View.VISIBLE);
- }
- });
return a;
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 4931dca..032ed78 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -34,7 +34,7 @@
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.LooperExecuter;
+import com.android.launcher3.util.LooperExecutor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -55,7 +55,7 @@
public ModelWriter(Context context, BgDataModel dataModel, boolean hasVerticalHotseat) {
mContext = context;
mBgDataModel = dataModel;
- mWorkerExecutor = new LooperExecuter(LauncherModel.getWorkerLooper());
+ mWorkerExecutor = new LooperExecutor(LauncherModel.getWorkerLooper());
mHasVerticalHotseat = hasVerticalHotseat;
}
diff --git a/src/com/android/launcher3/util/LooperExecuter.java b/src/com/android/launcher3/util/LooperExecutor.java
similarity index 94%
rename from src/com/android/launcher3/util/LooperExecuter.java
rename to src/com/android/launcher3/util/LooperExecutor.java
index 4db999b..5b7c20b 100644
--- a/src/com/android/launcher3/util/LooperExecuter.java
+++ b/src/com/android/launcher3/util/LooperExecutor.java
@@ -25,11 +25,11 @@
/**
* Extension of {@link AbstractExecutorService} which executed on a provided looper.
*/
-public class LooperExecuter extends AbstractExecutorService {
+public class LooperExecutor extends AbstractExecutorService {
private final Handler mHandler;
- public LooperExecuter(Looper looper) {
+ public LooperExecutor(Looper looper) {
mHandler = new Handler(looper);
}
diff --git a/src/com/android/launcher3/util/LooperIdleLock.java b/src/com/android/launcher3/util/LooperIdleLock.java
new file mode 100644
index 0000000..35cac14
--- /dev/null
+++ b/src/com/android/launcher3/util/LooperIdleLock.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.os.Looper;
+import android.os.MessageQueue;
+
+import com.android.launcher3.Utilities;
+
+/**
+ * Utility class to block execution until the UI looper is idle.
+ */
+public class LooperIdleLock implements MessageQueue.IdleHandler, Runnable {
+
+ private final Object mLock;
+
+ private boolean mIsLocked;
+
+ public LooperIdleLock(Object lock, Looper looper) {
+ mLock = lock;
+ mIsLocked = true;
+ if (Utilities.ATLEAST_MARSHMALLOW) {
+ looper.getQueue().addIdleHandler(this);
+ } else {
+ // Looper.myQueue() only gives the current queue. Move the execution to the UI thread
+ // so that the IdleHandler is attached to the correct message queue.
+ new LooperExecutor(looper).execute(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ Looper.myQueue().addIdleHandler(this);
+ }
+
+ @Override
+ public boolean queueIdle() {
+ synchronized (mLock) {
+ mIsLocked = false;
+ mLock.notify();
+ }
+ return false;
+ }
+
+ public boolean awaitLocked(long ms) {
+ if (mIsLocked) {
+ try {
+ // Just in case mFlushingWorkerThread changes but we aren't woken up,
+ // wait no longer than 1sec at a time
+ mLock.wait(ms);
+ } catch (InterruptedException ex) {
+ // Ignore
+ }
+ }
+ return mIsLocked;
+ }
+}
diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
index 9bd2882..4cb6ca8 100644
--- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java
+++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
@@ -16,12 +16,10 @@
package com.android.launcher3.util;
-import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewTreeObserver.OnDrawListener;
-import com.android.launcher3.DeferredHandler;
import com.android.launcher3.Launcher;
import java.util.ArrayList;
@@ -34,7 +32,7 @@
OnAttachStateChangeListener {
private final ArrayList<Runnable> mTasks = new ArrayList<>();
- private final DeferredHandler mHandler;
+ private final Executor mExecutor;
private Launcher mLauncher;
private View mAttachedView;
@@ -43,8 +41,8 @@
private boolean mLoadAnimationCompleted;
private boolean mFirstDrawCompleted;
- public ViewOnDrawExecutor(DeferredHandler handler) {
- mHandler = handler;
+ public ViewOnDrawExecutor(Executor executor) {
+ mExecutor = executor;
}
public void attachTo(Launcher launcher) {
@@ -92,7 +90,7 @@
// Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called.
if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) {
for (final Runnable r : mTasks) {
- mHandler.post(r);
+ mExecutor.execute(r);
}
markCompleted();
}
diff --git a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index 2ad3cba..13e0986 100644
--- a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -16,7 +16,6 @@
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppFilter;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.DeferredHandler;
import com.android.launcher3.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
@@ -36,6 +35,7 @@
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.Executor;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.atLeast;
@@ -102,14 +102,14 @@
f.setAccessible(true);
f.set(task, mockModel);
- DeferredHandler mockHandler = mock(DeferredHandler.class);
- f = BaseModelUpdateTask.class.getDeclaredField("mUiHandler");
+ Executor mockExecutor = mock(Executor.class);
+ f = BaseModelUpdateTask.class.getDeclaredField("mUiExecutor");
f.setAccessible(true);
- f.set(task, mockHandler);
+ f.set(task, mockExecutor);
task.execute(appState, bgDataModel, allAppsList);
ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
- verify(mockHandler, atLeast(0)).post(captor.capture());
+ verify(mockExecutor, atLeast(0)).execute(captor.capture());
return captor.getAllValues();
}
diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
index df2b662..97f7b50 100644
--- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java
@@ -39,13 +39,12 @@
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.ui.LauncherInstrumentationTestCase;
import com.android.launcher3.util.ContentWriter;
-import com.android.launcher3.util.LooperExecuter;
+import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetHostViewLoader;
import java.util.Set;
import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
@@ -340,7 +339,7 @@
* Blocks the current thread until all the jobs in the main worker thread are complete.
*/
private void waitUntilLoaderIdle() throws Exception {
- new LooperExecuter(LauncherModel.getWorkerLooper())
+ new LooperExecutor(LauncherModel.getWorkerLooper())
.submit(new Runnable() {
@Override
public void run() { }