Merge "Fix HUN launch animation" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
855929568b
@@ -204,6 +204,12 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NotificationEntry entry = alertEntry.mEntry;
|
NotificationEntry entry = alertEntry.mEntry;
|
||||||
|
|
||||||
|
// If the notification is animating, we will remove it at the end of the animation.
|
||||||
|
if (entry != null && entry.isExpandAnimationRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mAlertEntries.remove(key);
|
mAlertEntries.remove(key);
|
||||||
onAlertEntryRemoved(alertEntry);
|
onAlertEntryRemoved(alertEntry);
|
||||||
entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
entry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
|||||||
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
||||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||||
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
|
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
|
||||||
|
import com.android.systemui.statusbar.policy.HeadsUpUtil
|
||||||
import kotlin.math.ceil
|
import kotlin.math.ceil
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@@ -22,8 +23,8 @@ class NotificationLaunchAnimatorControllerProvider(
|
|||||||
return NotificationLaunchAnimatorController(
|
return NotificationLaunchAnimatorController(
|
||||||
notificationShadeWindowViewController,
|
notificationShadeWindowViewController,
|
||||||
notificationListContainer,
|
notificationListContainer,
|
||||||
notification,
|
headsUpManager,
|
||||||
headsUpManager
|
notification
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,10 +37,11 @@ class NotificationLaunchAnimatorControllerProvider(
|
|||||||
class NotificationLaunchAnimatorController(
|
class NotificationLaunchAnimatorController(
|
||||||
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
private val notificationShadeWindowViewController: NotificationShadeWindowViewController,
|
||||||
private val notificationListContainer: NotificationListContainer,
|
private val notificationListContainer: NotificationListContainer,
|
||||||
private val notification: ExpandableNotificationRow,
|
private val headsUpManager: HeadsUpManagerPhone,
|
||||||
private val headsUpManager: HeadsUpManagerPhone
|
private val notification: ExpandableNotificationRow
|
||||||
) : ActivityLaunchAnimator.Controller {
|
) : ActivityLaunchAnimator.Controller {
|
||||||
private val notificationKey = notification.entry.sbn.key
|
private val notificationEntry = notification.entry
|
||||||
|
private val notificationKey = notificationEntry.sbn.key
|
||||||
|
|
||||||
override var launchContainer: ViewGroup
|
override var launchContainer: ViewGroup
|
||||||
get() = notification.rootView as ViewGroup
|
get() = notification.rootView as ViewGroup
|
||||||
@@ -82,6 +84,7 @@ class NotificationLaunchAnimatorController(
|
|||||||
|
|
||||||
override fun onIntentStarted(willAnimate: Boolean) {
|
override fun onIntentStarted(willAnimate: Boolean) {
|
||||||
notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate)
|
notificationShadeWindowViewController.setExpandAnimationRunning(willAnimate)
|
||||||
|
notificationEntry.isExpandAnimationRunning = willAnimate
|
||||||
|
|
||||||
if (!willAnimate) {
|
if (!willAnimate) {
|
||||||
removeHun(animate = true)
|
removeHun(animate = true)
|
||||||
@@ -93,6 +96,7 @@ class NotificationLaunchAnimatorController(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(notification, animate)
|
||||||
headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate)
|
headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +104,7 @@ class NotificationLaunchAnimatorController(
|
|||||||
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
|
// TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started
|
||||||
// here?
|
// here?
|
||||||
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
||||||
|
notificationEntry.isExpandAnimationRunning = false
|
||||||
removeHun(animate = true)
|
removeHun(animate = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +121,7 @@ class NotificationLaunchAnimatorController(
|
|||||||
|
|
||||||
notification.isExpandAnimationRunning = false
|
notification.isExpandAnimationRunning = false
|
||||||
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
notificationShadeWindowViewController.setExpandAnimationRunning(false)
|
||||||
|
notificationEntry.isExpandAnimationRunning = false
|
||||||
notificationListContainer.setExpandingNotification(null)
|
notificationListContainer.setExpandingNotification(null)
|
||||||
applyParams(null)
|
applyParams(null)
|
||||||
removeHun(animate = false)
|
removeHun(animate = false)
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
private boolean mIsAlerting;
|
private boolean mIsAlerting;
|
||||||
|
|
||||||
public boolean mRemoteEditImeVisible;
|
public boolean mRemoteEditImeVisible;
|
||||||
|
private boolean mExpandAnimationRunning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sbn the StatusBarNotification from system server
|
* @param sbn the StatusBarNotification from system server
|
||||||
@@ -952,6 +953,16 @@ public final class NotificationEntry extends ListEntry {
|
|||||||
return mIsAlerting;
|
return mIsAlerting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set whether this notification is currently used to animate a launch. */
|
||||||
|
public void setExpandAnimationRunning(boolean expandAnimationRunning) {
|
||||||
|
mExpandAnimationRunning = expandAnimationRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether this notification is currently used to animate a launch. */
|
||||||
|
public boolean isExpandAnimationRunning() {
|
||||||
|
return mExpandAnimationRunning;
|
||||||
|
}
|
||||||
|
|
||||||
/** Information about a suggestion that is being edited. */
|
/** Information about a suggestion that is being edited. */
|
||||||
public static class EditedSuggestionInfo {
|
public static class EditedSuggestionInfo {
|
||||||
|
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ public class ViewState implements Dumpable {
|
|||||||
animator.addListener(new AnimatorListenerAdapter() {
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
HeadsUpUtil.setIsClickedHeadsUpNotification(child, false);
|
HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(child, false);
|
||||||
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
|
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
|
||||||
child.setTag(TAG_START_TRANSLATION_Y, null);
|
child.setTag(TAG_START_TRANSLATION_Y, null);
|
||||||
child.setTag(TAG_END_TRANSLATION_Y, null);
|
child.setTag(TAG_END_TRANSLATION_Y, null);
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ class StatusBarLaunchAnimatorController(
|
|||||||
|
|
||||||
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
|
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
|
||||||
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
|
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
|
||||||
statusBar.onLaunchAnimationEnd(isExpandingFullyAbove)
|
|
||||||
statusBar.notificationPanelViewController.setIsLaunchAnimationRunning(false)
|
statusBar.notificationPanelViewController.setIsLaunchAnimationRunning(false)
|
||||||
|
statusBar.onLaunchAnimationEnd(isExpandingFullyAbove)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLaunchAnimationProgress(
|
override fun onLaunchAnimationProgress(
|
||||||
|
|||||||
@@ -282,15 +282,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
boolean showOverLockscreen) {
|
boolean showOverLockscreen) {
|
||||||
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
|
mLogger.logHandleClickAfterKeyguardDismissed(entry.getKey());
|
||||||
|
|
||||||
// TODO: Some of this code may be able to move to NotificationEntryManager.
|
|
||||||
String key = row.getEntry().getSbn().getKey();
|
|
||||||
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
|
|
||||||
// Release the HUN notification to the shade.
|
|
||||||
if (mPresenter.isPresenterFullyCollapsed()) {
|
|
||||||
HeadsUpUtil.setIsClickedHeadsUpNotification(row, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
|
final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed(
|
||||||
entry, row, controller, intent,
|
entry, row, controller, intent,
|
||||||
isActivityIntent, animate);
|
isActivityIntent, animate);
|
||||||
@@ -337,7 +328,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
// bypass work challenge
|
// bypass work challenge
|
||||||
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
|
if (mStatusBarRemoteInputCallback.startWorkChallengeIfNecessary(userId,
|
||||||
intent.getIntentSender(), notificationKey)) {
|
intent.getIntentSender(), notificationKey)) {
|
||||||
removeHUN(row);
|
removeHunAfterClick(row);
|
||||||
// Show work challenge, do not run PendingIntent and
|
// Show work challenge, do not run PendingIntent and
|
||||||
// remove notification
|
// remove notification
|
||||||
collapseOnMainThread();
|
collapseOnMainThread();
|
||||||
@@ -357,7 +348,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
final boolean canBubble = entry.canBubble();
|
final boolean canBubble = entry.canBubble();
|
||||||
if (canBubble) {
|
if (canBubble) {
|
||||||
mLogger.logExpandingBubble(notificationKey);
|
mLogger.logExpandingBubble(notificationKey);
|
||||||
removeHUN(row);
|
removeHunAfterClick(row);
|
||||||
expandBubbleStackOnMainThread(entry);
|
expandBubbleStackOnMainThread(entry);
|
||||||
} else {
|
} else {
|
||||||
startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent);
|
startNotificationIntent(intent, fillInIntent, entry, row, animate, isActivityIntent);
|
||||||
@@ -508,9 +499,14 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
|
|||||||
}, null, false /* afterKeyguardGone */);
|
}, null, false /* afterKeyguardGone */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeHUN(ExpandableNotificationRow row) {
|
private void removeHunAfterClick(ExpandableNotificationRow row) {
|
||||||
String key = row.getEntry().getSbn().getKey();
|
String key = row.getEntry().getSbn().getKey();
|
||||||
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
|
if (mHeadsUpManager != null && mHeadsUpManager.isAlerting(key)) {
|
||||||
|
// Release the HUN notification to the shade.
|
||||||
|
if (mPresenter.isPresenterFullyCollapsed()) {
|
||||||
|
HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(row, true);
|
||||||
|
}
|
||||||
|
|
||||||
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
|
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
|
||||||
// become canceled shortly by NoMan, but we can't assume that.
|
// become canceled shortly by NoMan, but we can't assume that.
|
||||||
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
|
mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public final class HeadsUpUtil {
|
|||||||
* @param view The view to be set the flag to.
|
* @param view The view to be set the flag to.
|
||||||
* @param clicked True to set as clicked. False to not-clicked.
|
* @param clicked True to set as clicked. False to not-clicked.
|
||||||
*/
|
*/
|
||||||
public static void setIsClickedHeadsUpNotification(View view, boolean clicked) {
|
public static void setNeedsHeadsUpDisappearAnimationAfterClick(View view, boolean clicked) {
|
||||||
view.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
|
view.setTag(TAG_CLICKED_NOTIFICATION, clicked ? true : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.android.systemui.statusbar.notification
|
||||||
|
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||||
|
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
|
||||||
|
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
|
||||||
|
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||||
|
import com.android.systemui.statusbar.phone.NotificationShadeWindowViewController
|
||||||
|
import com.android.systemui.statusbar.policy.HeadsUpUtil
|
||||||
|
import junit.framework.Assert.assertFalse
|
||||||
|
import junit.framework.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@RunWithLooper
|
||||||
|
class NotificationLaunchAnimatorControllerTest : SysuiTestCase() {
|
||||||
|
@Mock lateinit var notificationShadeWindowViewController: NotificationShadeWindowViewController
|
||||||
|
@Mock lateinit var notificationListContainer: NotificationListContainer
|
||||||
|
@Mock lateinit var headsUpManager: HeadsUpManagerPhone
|
||||||
|
|
||||||
|
private lateinit var notificationTestHelper: NotificationTestHelper
|
||||||
|
private lateinit var notification: ExpandableNotificationRow
|
||||||
|
private lateinit var controller: NotificationLaunchAnimatorController
|
||||||
|
|
||||||
|
private val notificationKey: String
|
||||||
|
get() = notification.entry.sbn.key
|
||||||
|
|
||||||
|
@get:Rule val rule = MockitoJUnit.rule()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
allowTestableLooperAsMainThread()
|
||||||
|
notificationTestHelper =
|
||||||
|
NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
|
||||||
|
notification = notificationTestHelper.createRow()
|
||||||
|
controller = NotificationLaunchAnimatorController(
|
||||||
|
notificationShadeWindowViewController,
|
||||||
|
notificationListContainer,
|
||||||
|
headsUpManager,
|
||||||
|
notification
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun flagNotificationAsHun() {
|
||||||
|
`when`(headsUpManager.isAlerting(notificationKey)).thenReturn(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHunIsRemovedIfWeDontAnimateLaunch() {
|
||||||
|
flagNotificationAsHun()
|
||||||
|
controller.onIntentStarted(willAnimate = false)
|
||||||
|
|
||||||
|
assertTrue(HeadsUpUtil.isClickedHeadsUpNotification(notification))
|
||||||
|
assertFalse(notification.entry.isExpandAnimationRunning)
|
||||||
|
verify(headsUpManager).removeNotification(
|
||||||
|
notificationKey, true /* releaseImmediately */, true /* animate */)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHunIsRemovedWhenAnimationIsCancelled() {
|
||||||
|
flagNotificationAsHun()
|
||||||
|
controller.onLaunchAnimationCancelled()
|
||||||
|
|
||||||
|
assertTrue(HeadsUpUtil.isClickedHeadsUpNotification(notification))
|
||||||
|
assertFalse(notification.entry.isExpandAnimationRunning)
|
||||||
|
verify(headsUpManager).removeNotification(
|
||||||
|
notificationKey, true /* releaseImmediately */, true /* animate */)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHunIsRemovedWhenAnimationEnds() {
|
||||||
|
flagNotificationAsHun()
|
||||||
|
controller.onLaunchAnimationEnd(isExpandingFullyAbove = true)
|
||||||
|
|
||||||
|
assertFalse(HeadsUpUtil.isClickedHeadsUpNotification(notification))
|
||||||
|
assertFalse(notification.entry.isExpandAnimationRunning)
|
||||||
|
verify(headsUpManager).removeNotification(
|
||||||
|
notificationKey, true /* releaseImmediately */, false /* animate */)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotificationIsExpandingDuringAnimation() {
|
||||||
|
controller.onIntentStarted(willAnimate = true)
|
||||||
|
|
||||||
|
assertTrue(notification.entry.isExpandAnimationRunning)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user