Moving discovery bounce logic to a separate class.

Removing special transition handling around discovery bound to avoid
inconsistant UI state

Change-Id: Ia40bcb0719076021a6c96f1bd16d44da0286a209
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 2c6629d..da464c0 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -59,6 +59,10 @@
             | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
             | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP;
 
+    // Type of popups which should be kept open during launcher rebind
+    public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
+            | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP;
+
     protected boolean mIsOpen;
 
     public AbstractFloatingView(Context context, AttributeSet attrs) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 44b64d9..6b6029d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -60,7 +60,6 @@
 import android.content.pm.PackageManager;
 import android.database.sqlite.SQLiteDatabase;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
@@ -99,10 +98,10 @@
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.compat.AppWidgetManagerCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.LauncherAppsCompatVO;
-import com.android.launcher3.compat.UserManagerCompat;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
@@ -121,7 +120,6 @@
 import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.popup.PopupDataProvider;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
-import com.android.launcher3.states.AllAppsState;
 import com.android.launcher3.states.InternalStateHandler;
 import com.android.launcher3.uioverrides.UiFactory;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -848,9 +846,7 @@
         // Refresh shortcuts if the permission changed.
         mModel.refreshShortcutsIfRequired();
 
-        if (shouldShowDiscoveryBounce()) {
-            mAllAppsController.showDiscoveryBounce();
-        }
+        DiscoveryBounce.showIfNeeded(this);
         if (mLauncherCallbacks != null) {
             mLauncherCallbacks.onResume();
         }
@@ -1040,7 +1036,7 @@
                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
 
         // Setup the drag layer
-        mDragLayer.setup(this, mDragController, mAllAppsController);
+        mDragLayer.setup(this, mDragController);
 
         // Setup the hotseat
         mHotseat = (Hotseat) findViewById(R.id.hotseat);
@@ -2429,7 +2425,7 @@
         // we are starting a fresh bind, close all such panels as all the icons are about
         // to go away.
         AbstractFloatingView.closeOpenViews(this, true,
-                AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_WIDGETS_FULL_SHEET);
+                AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
 
         setWorkspaceLoading(true);
 
@@ -3070,12 +3066,6 @@
         return mRotationEnabled;
     }
 
-    private boolean shouldShowDiscoveryBounce() {
-        return isInState(NORMAL)
-                && !mSharedPrefs.getBoolean(AllAppsState.APPS_VIEW_SHOWN, false)
-                && !UserManagerCompat.getInstance(this).isDemoUser();
-    }
-
     /**
      * $ adb shell dumpsys activity com.android.launcher3.Launcher [--all]
      */
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index eb26704..1ec7ac0 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -4,7 +4,6 @@
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 
 import android.animation.Animator;
-import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
@@ -77,8 +76,6 @@
 
     private static final float DEFAULT_SHIFT_RANGE = 10;
 
-    private boolean mIsTranslateWithoutWorkspace = false;
-    private Animator mDiscoBounceAnimation;
     private GradientView mGradientView;
 
     public AllAppsTransitionController(Launcher l) {
@@ -149,10 +146,6 @@
                     PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent),
                     hotseatAlpha);
         }
-
-        if (mIsTranslateWithoutWorkspace) {
-            return;
-        }
         mWorkspace.setWorkspaceYTranslationAndAlpha(
                 PARALLAX_COEFFICIENT * (-mShiftRange + shiftCurrent), workspaceAlpha);
 
@@ -191,7 +184,13 @@
                 this, PROGRESS, mProgress, toState.verticalProgress);
         anim.setDuration(config.duration);
         anim.setInterpolator(interpolator);
-        anim.addListener(new AnimationSuccessListener() {
+        anim.addListener(getProgressAnimatorListener());
+
+        animationOut.play(anim);
+    }
+
+    public AnimatorListenerAdapter getProgressAnimatorListener() {
+        return new AnimationSuccessListener() {
             @Override
             public void onAnimationSuccess(Animator animator) {
                 onProgressAnimationEnd();
@@ -201,50 +200,7 @@
             public void onAnimationStart(Animator animation) {
                 onProgressAnimationStart();
             }
-        });
-
-        animationOut.play(anim);
-    }
-
-    public void showDiscoveryBounce() {
-        // cancel existing animation in case user locked and unlocked at a super human speed.
-        cancelDiscoveryAnimation();
-
-        // assumption is that this variable is always null
-        mDiscoBounceAnimation = AnimatorInflater.loadAnimator(mLauncher,
-                R.animator.discovery_bounce);
-        mDiscoBounceAnimation.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animator) {
-                mIsTranslateWithoutWorkspace = true;
-                onProgressAnimationStart();
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animator) {
-                onProgressAnimationEnd();
-                mDiscoBounceAnimation = null;
-                mIsTranslateWithoutWorkspace = false;
-            }
-        });
-        mDiscoBounceAnimation.setTarget(this);
-        mAppsView.post(new Runnable() {
-            @Override
-            public void run() {
-                if (mDiscoBounceAnimation == null) {
-                    return;
-                }
-                mDiscoBounceAnimation.start();
-            }
-        });
-    }
-
-    public void cancelDiscoveryAnimation() {
-        if (mDiscoBounceAnimation == null) {
-            return;
-        }
-        mDiscoBounceAnimation.cancel();
-        mDiscoBounceAnimation = null;
+        };
     }
 
     public void setupViews(AllAppsContainerView appsView, Hotseat hotseat, Workspace workspace) {
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
new file mode 100644
index 0000000..9723545
--- /dev/null
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -0,0 +1,108 @@
+/*
+ * 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.allapps;
+
+import static com.android.launcher3.LauncherState.NORMAL;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.view.MotionEvent;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.states.AllAppsState;
+
+/**
+ * Floating view responsible for showing discovery bounce animation
+ */
+public class DiscoveryBounce extends AbstractFloatingView {
+
+    private final Launcher mLauncher;
+    private final Animator mDiscoBounceAnimation;
+
+    public DiscoveryBounce(Launcher launcher) {
+        super(launcher, null);
+        mLauncher = launcher;
+
+        mDiscoBounceAnimation = AnimatorInflater.loadAnimator(mLauncher,
+                R.animator.discovery_bounce);
+        AllAppsTransitionController controller = mLauncher.getAllAppsController();
+        mDiscoBounceAnimation.setTarget(controller);
+        mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
+
+        mDiscoBounceAnimation.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                handleClose(false);
+            }
+        });
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mDiscoBounceAnimation.start();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mDiscoBounceAnimation.isRunning()) {
+            mDiscoBounceAnimation.end();
+        }
+    }
+
+    @Override
+    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+        handleClose(false);
+        return false;
+    }
+
+    @Override
+    protected void handleClose(boolean animate) {
+        if (mIsOpen) {
+            mIsOpen = false;
+            mLauncher.getDragLayer().removeView(this);
+        }
+    }
+
+    @Override
+    public void logActionCommand(int command) {
+        // Since this is on-boarding popup, it is not a user controlled action.
+    }
+
+    @Override
+    protected boolean isOfType(int type) {
+        return (type & TYPE_ON_BOARD_POPUP) != 0;
+    }
+
+    public static void showIfNeeded(Launcher launcher) {
+        if (!launcher.isInState(NORMAL)
+                || launcher.getSharedPrefs().getBoolean(AllAppsState.APPS_VIEW_SHOWN, false)
+                || AbstractFloatingView.getTopOpenView(launcher) != null
+                || UserManagerCompat.getInstance(launcher).isDemoUser()) {
+            return;
+        }
+
+        DiscoveryBounce view = new DiscoveryBounce(launcher);
+        view.mIsOpen = true;
+        launcher.getDragLayer().addView(view);
+    }
+}
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 9f9822c..cf76e2e 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -45,7 +45,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsTransitionController;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
@@ -90,9 +89,6 @@
     private final ViewGroupFocusHelper mFocusIndicatorHelper;
     private final PageCutOutScrimDrawable mPageCutOutScrim;
 
-    // Handles all apps pull up interaction
-    private AllAppsTransitionController mAllAppsController;
-
     protected TouchController[] mControllers;
     private TouchController mActiveController;
     /**
@@ -113,11 +109,9 @@
         mPageCutOutScrim.setCallback(this);
     }
 
-    public void setup(Launcher launcher, DragController dragController,
-            AllAppsTransitionController allAppsTransitionController) {
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
         mDragController = dragController;
-        mAllAppsController = allAppsTransitionController;
         mControllers = UiFactory.createTouchControllers(mLauncher);
     }
 
@@ -156,12 +150,7 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
 
-        if (action == MotionEvent.ACTION_DOWN) {
-            // Cancel discovery bounce animation when a user start interacting on anywhere on
-            // dray layer even if mAllAppsController is NOT the active controller.
-            // TODO: handle other input other than touch
-            mAllAppsController.cancelDiscoveryAnimation();
-        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
             if (mTouchCompleteListener != null) {
                 mTouchCompleteListener.onTouchComplete();
             }
@@ -800,6 +789,6 @@
     }
 
     public interface TouchCompleteListener {
-        public void onTouchComplete();
+        void onTouchComplete();
     }
 }