Added NotificationWakeUpCoordinator to coordinate wakeups better

The goal is to be able to reuse the same logic for pulsing
as well as for the drag down and wake up.

Test: atest SystemUITests
Bug: 125942236
Change-Id: I5247cdfdd3e8572e9f6faf5eaaee70eed4aa2efc
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
new file mode 100644
index 0000000..f3c8e6f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 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.systemui.statusbar.notification
+
+import android.animation.ObjectAnimator
+import android.util.FloatProperty
+import android.view.animation.Interpolator
+import com.android.systemui.Interpolators
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class NotificationWakeUpCoordinator @Inject constructor() {
+
+    private val mNotificationVisibility
+            = object : FloatProperty<NotificationWakeUpCoordinator>("notificationVisibility") {
+
+        override fun setValue(coordinator: NotificationWakeUpCoordinator, value: Float) {
+            coordinator.setVisibilityAmount(value)
+        }
+
+        override fun get(coordinator: NotificationWakeUpCoordinator): Float? {
+            return coordinator.mLinearVisibilityAmount
+        }
+    }
+    private lateinit var mStackScroller: NotificationStackScrollLayout
+    private var mVisibilityInterpolator = Interpolators.FAST_OUT_SLOW_IN_REVERSE
+
+    private var mLinearDozeAmount: Float = 0.0f
+    private var mDozeAmount: Float = 0.0f
+    private var mNotificationVisibleAmount = 0.0f
+    private var mNotificationsVisible = false
+    private var mDarkAnimator: ObjectAnimator? = null
+    private var mVisibilityAmount = 0.0f
+    private var mLinearVisibilityAmount = 0.0f
+
+    fun setStackScroller(stackScroller: NotificationStackScrollLayout) {
+        mStackScroller = stackScroller
+    }
+
+    fun setNotificationsVisible(visible: Boolean, animate: Boolean) {
+        if (mNotificationsVisible == visible) {
+            return
+        }
+        mNotificationsVisible = visible
+        mDarkAnimator?.cancel();
+        if (animate) {
+            startVisibilityAnimation()
+            notifyAnimationStart(visible)
+        } else {
+            setVisibilityAmount(if (visible) 1.0f else 0.0f)
+        }
+    }
+
+    fun setDozeAmount(linearAmount: Float, interpolatedAmount: Float) {
+        mLinearDozeAmount = linearAmount;
+        mDozeAmount = interpolatedAmount;
+        updateDarkAmount()
+    }
+
+    private fun startVisibilityAnimation() {
+        if (mNotificationVisibleAmount == 0f || mNotificationVisibleAmount == 1f) {
+            mVisibilityInterpolator = if (mNotificationsVisible)
+                Interpolators.TOUCH_RESPONSE_REVERSE
+            else
+                Interpolators.FAST_OUT_SLOW_IN
+        }
+        val target = if (mNotificationsVisible) 1.0f else 0.0f
+        val darkAnimator = ObjectAnimator.ofFloat(this, mNotificationVisibility, target)
+        darkAnimator.setInterpolator(Interpolators.LINEAR)
+        darkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP.toLong())
+        darkAnimator.start()
+        mDarkAnimator = darkAnimator
+    }
+
+    private fun setVisibilityAmount(visibilityAmount: Float) {
+        mLinearVisibilityAmount = visibilityAmount
+        mVisibilityAmount = mVisibilityInterpolator.getInterpolation(
+                visibilityAmount)
+        updateDarkAmount()
+    }
+
+    private fun updateDarkAmount() {
+        val linearAmount = Math.min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
+        val amount = Math.min(1.0f - mVisibilityAmount, mDozeAmount)
+        mStackScroller.setDarkAmount(linearAmount, amount)
+    }
+
+    fun notifyAnimationStart(awake: Boolean) {
+        mStackScroller.notifyDarkAnimationStart(!awake)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f4fa1e8..ce4d95f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -19,6 +19,9 @@
 import static com.android.systemui.SysUiServiceProvider.getComponent;
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
 
+
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -77,6 +80,7 @@
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -96,6 +100,9 @@
 import java.util.List;
 import java.util.function.Consumer;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 public class NotificationPanelView extends PanelView implements
         ExpandableView.OnHeightChangedListener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
@@ -136,6 +143,7 @@
 
     private final PowerManager mPowerManager;
     private final AccessibilityManager mAccessibilityManager;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
 
     private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -317,11 +325,14 @@
             Dependency.get(ShadeController.class);
     private int mDisplayId;
 
-    public NotificationPanelView(Context context, AttributeSet attrs) {
+    @Inject
+    public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+            NotificationWakeUpCoordinator coordinator) {
         super(context, attrs);
         setWillNotDraw(!DEBUG);
         mFalsingManager = FalsingManager.getInstance(context);
         mPowerManager = context.getSystemService(PowerManager.class);
+        mWakeUpCoordinator = coordinator;
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
         setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
         mAlphaPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
@@ -364,6 +375,7 @@
 
         initBottomArea();
 
+        mWakeUpCoordinator.setStackScroller(mNotificationStackScroller);
         mQsFrame = findViewById(R.id.qs_frame);
     }
 
@@ -2813,7 +2825,7 @@
         final float darkAmount = dozing ? 1 : 0;
         mStatusBarStateController.setDozeAmount(darkAmount, animate);
         if (animate) {
-            mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
+            mWakeUpCoordinator.notifyAnimationStart(!mDozing);
         }
     }
 
@@ -2825,7 +2837,7 @@
         mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount);
         mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
         positionClockAndNotifications();
-        mNotificationStackScroller.setDarkAmount(linearAmount, mInterpolatedDarkAmount);
+        mWakeUpCoordinator.setDozeAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
     }
 
     public void setPulsing(boolean pulsing) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index faebf60..c6636b4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -27,6 +27,7 @@
 import com.android.systemui.qs.QSFooterImpl;
 import com.android.systemui.qs.QuickStatusBarHeader;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -118,6 +119,11 @@
          * Creates the NotificationStackScrollLayout.
          */
         NotificationStackScrollLayout createNotificationStackScrollLayout();
+
+        /**
+         * Creates the NotificationPanelView.
+         */
+        NotificationPanelView createPanelView();
     }
 
     /**