Merge "Restoring 10-sec wait for model initialization" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index 3d1ecef..f889bc1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -75,6 +75,9 @@
     @Override
     public void onSwipeUpToRecentsComplete() {
         RecentsActivity activity = getCreatedActivity();
+        if (activity == null) {
+            return;
+        }
         RecentsView recentsView = activity.getOverviewPanel();
         recentsView.getClearAllButton().setVisibilityAlpha(1);
         recentsView.setDisallowScrollToClearAll(false);
@@ -236,12 +239,18 @@
     public void onLaunchTaskFailed() {
         // TODO: probably go back to overview instead.
         RecentsActivity activity = getCreatedActivity();
+        if (activity == null) {
+            return;
+        }
         activity.<RecentsView>getOverviewPanel().startHome();
     }
 
     @Override
     public void onLaunchTaskSuccess() {
         RecentsActivity activity = getCreatedActivity();
+        if (activity == null) {
+            return;
+        }
         activity.onTaskLaunched();
     }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 4406314..48b8fc6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -94,6 +94,9 @@
     @Override
     public void onTransitionCancelled(boolean activityVisible) {
         Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         LauncherState startState = launcher.getStateManager().getRestState();
         launcher.getStateManager().goToState(startState, activityVisible);
     }
@@ -102,32 +105,40 @@
     public void onSwipeUpToRecentsComplete() {
         // Re apply state in case we did something funky during the transition.
         Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         launcher.getStateManager().reapplyState();
         DiscoveryBounce.showForOverviewIfNeeded(launcher);
     }
 
     @Override
     public void onSwipeUpToHomeComplete() {
+        Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         // Ensure recents is at the correct position for NORMAL state. For example, when we detach
         // recents, we assume the first task is invisible, making translation off by one task.
-        Launcher launcher = getCreatedActivity();
         launcher.getStateManager().reapplyState();
         setLauncherHideBackArrow(false);
     }
 
     private void setLauncherHideBackArrow(boolean hideBackArrow) {
         Launcher launcher = getCreatedActivity();
-        if (launcher != null) {
-            launcher.getRootView().setForceHideBackArrow(hideBackArrow);
+        if (launcher == null) {
+            return;
         }
+        launcher.getRootView().setForceHideBackArrow(hideBackArrow);
     }
 
     @Override
     public void onAssistantVisibilityChanged(float visibility) {
         Launcher launcher = getCreatedActivity();
-        if (launcher != null) {
-            launcher.onAssistantVisibilityChanged(visibility);
+        if (launcher == null) {
+            return;
         }
+        launcher.onAssistantVisibilityChanged(visibility);
     }
 
     @NonNull
@@ -476,12 +487,18 @@
     @Override
     public void onLaunchTaskFailed() {
         Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         launcher.getStateManager().goToState(OVERVIEW);
     }
 
     @Override
     public void onLaunchTaskSuccess() {
         Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         launcher.getStateManager().moveToRestState();
     }
 
@@ -503,6 +520,9 @@
     public void switchRunningTaskViewToScreenshot(ThumbnailData thumbnailData,
             Runnable onFinishRunnable) {
         Launcher launcher = getCreatedActivity();
+        if (launcher == null) {
+            return;
+        }
         RecentsView recentsView = launcher.getOverviewPanel();
         if (recentsView == null) {
             if (onFinishRunnable != null) {
@@ -516,8 +536,9 @@
     @Override
     public void setOnDeferredActivityLaunchCallback(Runnable r) {
         Launcher launcher = getCreatedActivity();
-        if (launcher != null) {
-            launcher.setOnDeferredActivityLaunchCallback(r);
+        if (launcher == null) {
+            return;
         }
+        launcher.setOnDeferredActivityLaunchCallback(r);
     }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index 0a4f005..a00a6bd 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -300,8 +300,8 @@
 
     public LooperIdleLock newIdleLock(Object lock) {
         LooperIdleLock idleLock = new LooperIdleLock(lock, Looper.getMainLooper());
-        // If we are not binding, there is no reason to wait for idle.
-        if (mCallbacks.get() == null) {
+        // If we are not binding or if the main looper is already idle, there is no reason to wait
+        if (mCallbacks.get() == null || Looper.getMainLooper().getQueue().isIdle()) {
             idleLock.queueIdle();
         }
         return idleLock;
diff --git a/src/com/android/launcher3/util/LooperIdleLock.java b/src/com/android/launcher3/util/LooperIdleLock.java
index 2896535..f4ccf42 100644
--- a/src/com/android/launcher3/util/LooperIdleLock.java
+++ b/src/com/android/launcher3/util/LooperIdleLock.java
@@ -22,29 +22,30 @@
 /**
  * Utility class to block execution until the UI looper is idle.
  */
-public class LooperIdleLock implements MessageQueue.IdleHandler, Runnable {
+public class LooperIdleLock implements MessageQueue.IdleHandler {
 
     private final Object mLock;
 
     private boolean mIsLocked;
+    private Looper mLooper;
 
     public LooperIdleLock(Object lock, Looper looper) {
         mLock = lock;
+        mLooper = looper;
         mIsLocked = true;
         looper.getQueue().addIdleHandler(this);
     }
 
     @Override
-    public void run() {
-        Looper.myQueue().addIdleHandler(this);
-    }
-
-    @Override
     public boolean queueIdle() {
         synchronized (mLock) {
             mIsLocked = false;
             mLock.notify();
         }
+        // Manually remove from the list in case we're calling this outside of the idle callbacks
+        // (this is Ok in the normal flow as well because MessageQueue makes a copy of all handlers
+        // before calling back)
+        mLooper.getQueue().removeIdleHandler(this);
         return false;
     }
 
diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
index 61ba4e5..5a131c8 100644
--- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java
+++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java
@@ -55,7 +55,9 @@
             mLoadAnimationCompleted = true;
         }
 
-        attachObserver();
+        if (mAttachedView.isAttachedToWindow()) {
+            attachObserver();
+        }
     }
 
     private void attachObserver() {