diff options
9 files changed, 267 insertions, 20 deletions
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml index a5608af7a081..7aef82a8aa3a 100644 --- a/core/res/res/layout/notification_material_action_list.xml +++ b/core/res/res/layout/notification_material_action_list.xml @@ -27,6 +27,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="end" + android:layout_gravity="bottom" android:orientation="horizontal" android:background="@color/notification_action_list_background_color" > diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index e624441ca777..25fb24a3417f 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -221,6 +221,7 @@ android_library { "WindowManager-Shell", "LowLightDreamLib", "motion_tool_lib", + "androidx.core_core-animation-testing-nodeps", ], } diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml index a5b2f80a3158..f4b0a45a8d32 100644 --- a/packages/SystemUI/res/layout/remote_input.xml +++ b/packages/SystemUI/res/layout/remote_input.xml @@ -20,6 +20,7 @@ <com.android.systemui.statusbar.policy.RemoteInputView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/remote_input" + android:forceHasOverlappingRendering="false" android:layout_height="match_parent" android:layout_width="match_parent"> <LinearLayout diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 389639d23795..f3c03864382f 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -100,6 +100,11 @@ object Flags { // TODO(b/257315550): Tracking Bug val NO_HUN_FOR_OLD_WHEN = unreleasedFlag(118, "no_hun_for_old_when") + // TODO(b/260335638): Tracking Bug + @JvmField + val NOTIFICATION_INLINE_REPLY_ANIMATION = + unreleasedFlag(174148361, "notification_inline_reply_animation", teamfood = true) + val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD = unreleasedFlag(254647461, "filter_unseen_notifs_on_keyguard", teamfood = true) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java index f668528d8f5f..351603700f98 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java @@ -463,7 +463,11 @@ public class NotificationRemoteInputManager implements Dumpable { riv.getController().setRemoteInput(input); riv.getController().setRemoteInputs(inputs); riv.getController().setEditedSuggestionInfo(editedSuggestionInfo); - riv.focusAnimated(); + ViewGroup parent = view.getParent() != null ? (ViewGroup) view.getParent() : null; + if (parent != null) { + riv.setDefocusTargetHeight(parent.getHeight()); + } + riv.focusAnimated(parent); if (userMessageContent != null) { riv.setEditTextContent(userMessageContent); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 277ad8e54016..83d6abb4d977 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -70,7 +70,7 @@ import java.util.List; /** * A frame layout containing the actual payload of the notification, including the contracted, - * expanded and heads up layout. This class is responsible for clipping the content and and + * expanded and heads up layout. This class is responsible for clipping the content and * switching between the expanded, contracted and the heads up view depending on its clipped size. */ public class NotificationContentView extends FrameLayout implements NotificationFadeAware { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index dd400b3fc0ff..9f5ad1c5fddc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.policy; import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; +import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD; + import android.app.ActivityManager; import android.app.Notification; import android.content.Context; @@ -57,6 +57,7 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; @@ -67,6 +68,11 @@ import android.window.OnBackInvokedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.animation.Animator; +import androidx.core.animation.AnimatorListenerAdapter; +import androidx.core.animation.AnimatorSet; +import androidx.core.animation.ObjectAnimator; +import androidx.core.animation.ValueAnimator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; @@ -74,6 +80,7 @@ import com.android.internal.logging.UiEvent; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.animation.InterpolatorsAndroidX; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper; @@ -97,6 +104,12 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene // A marker object that let's us easily find views of this class. public static final Object VIEW_TAG = new Object(); + private static final long FOCUS_ANIMATION_TOTAL_DURATION = ANIMATION_DURATION_STANDARD; + private static final long FOCUS_ANIMATION_CROSSFADE_DURATION = 50; + private static final long FOCUS_ANIMATION_FADE_IN_DELAY = 33; + private static final long FOCUS_ANIMATION_FADE_IN_DURATION = 83; + private static final float FOCUS_ANIMATION_MIN_SCALE = 0.5f; + public final Object mToken = new Object(); private final SendButtonTextWatcher mTextWatcher; @@ -108,6 +121,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private RemoteEditText mEditText; private ImageButton mSendButton; + private LinearLayout mContentView; private GradientDrawable mContentBackground; private ProgressBar mProgressBar; private ImageView mDelete; @@ -115,7 +129,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private boolean mColorized; private int mTint; private boolean mResetting; - @Nullable private RevealParams mRevealParams; + @Nullable + private RevealParams mRevealParams; + private Rect mContentBackgroundBounds; + private boolean mIsFocusAnimationFlagActive; // TODO(b/193539698): move these to a Controller private RemoteInputController mController; @@ -125,6 +142,9 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene private boolean mSending; private NotificationViewWrapper mWrapper; + private Integer mDefocusTargetHeight = null; + + // TODO(b/193539698): remove this; views shouldn't have access to their controller, and places // that need the controller shouldn't have access to the view private RemoteInputViewController mViewController; @@ -255,8 +275,8 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mDeleteBg.setImageTintBlendMode(BlendMode.SRC_IN); mDelete.setImageTintBlendMode(BlendMode.SRC_IN); mDelete.setOnClickListener(v -> setAttachment(null)); - LinearLayout contentView = findViewById(R.id.remote_input_content); - contentView.setBackground(mContentBackground); + mContentView = findViewById(R.id.remote_input_content); + mContentView.setBackground(mContentBackground); mEditText = findViewById(R.id.remote_input_text); mEditText.setInnerFocusable(false); // TextView initializes the spell checked when the view is attached to a window. @@ -398,20 +418,70 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene return true; } - private void onDefocus(boolean animate, boolean logClose) { + /** + * View will ensure to use at most the provided defocusTargetHeight, when defocusing animated. + * This is to ensure that the parent can resize itself to the targetHeight while the defocus + * animation of the RemoteInputView is running. + * + * @param defocusTargetHeight The target height the parent will resize itself to. If null, the + * RemoteInputView will not resize itself. + */ + public void setDefocusTargetHeight(Integer defocusTargetHeight) { + mDefocusTargetHeight = defocusTargetHeight; + } + + @VisibleForTesting + void onDefocus(boolean animate, boolean logClose) { mController.removeRemoteInput(mEntry, mToken); mEntry.remoteInputText = mEditText.getText(); // During removal, we get reattached and lose focus. Not hiding in that // case to prevent flicker. if (!mRemoved) { - if (animate && mRevealParams != null && mRevealParams.radius > 0) { - Animator reveal = mRevealParams.createCircularHideAnimator(this); + if (animate && mIsFocusAnimationFlagActive) { + Animator animator = getDefocusAnimator(); + + // When defocusing, the notification needs to shrink. Therefore, we need to free + // up the space that is needed for the RemoteInputView. This is done by setting + // a negative top margin of the height difference of the RemoteInputView and its + // sibling (the actions_container_layout containing the Reply button) + if (mDefocusTargetHeight != null && mDefocusTargetHeight < getHeight() + && mDefocusTargetHeight >= 0 + && getLayoutParams() instanceof FrameLayout.LayoutParams) { + int heightToShrink = getHeight() - mDefocusTargetHeight; + FrameLayout.LayoutParams layoutParams = + (FrameLayout.LayoutParams) getLayoutParams(); + layoutParams.topMargin = -heightToShrink; + setLayoutParams(layoutParams); + ((ViewGroup) getParent().getParent()).setClipChildren(false); + } + + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + //reset top margin after the animation + if (getLayoutParams() instanceof FrameLayout.LayoutParams) { + FrameLayout.LayoutParams layoutParams = + (FrameLayout.LayoutParams) getLayoutParams(); + layoutParams.topMargin = 0; + setLayoutParams(layoutParams); + ((ViewGroup) getParent().getParent()).setClipChildren(true); + } + setVisibility(GONE); + if (mWrapper != null) { + mWrapper.setRemoteInputVisible(false); + } + } + }); + animator.start(); + + } else if (animate && mRevealParams != null && mRevealParams.radius > 0) { + android.animation.Animator reveal = mRevealParams.createCircularHideAnimator(this); reveal.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); reveal.setDuration(StackStateAnimator.ANIMATION_DURATION_CLOSE_REMOTE_INPUT); - reveal.addListener(new AnimatorListenerAdapter() { + reveal.addListener(new android.animation.AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEnd(android.animation.Animator animation) { setVisibility(GONE); if (mWrapper != null) { mWrapper.setRemoteInputVisible(false); @@ -533,12 +603,29 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setText(editTextContent); } - public void focusAnimated() { - if (getVisibility() != VISIBLE && mRevealParams != null) { - Animator animator = mRevealParams.createCircularRevealAnimator(this); + /** + * Sets whether the feature flag for the updated inline reply animation is active or not. + * @param active + */ + public void setIsFocusAnimationFlagActive(boolean active) { + mIsFocusAnimationFlagActive = active; + } + + /** + * Focuses the RemoteInputView and animates its appearance + * + * @param crossFadeView view that will be crossfaded during the appearance animation + */ + public void focusAnimated(View crossFadeView) { + if (!mIsFocusAnimationFlagActive && getVisibility() != VISIBLE + && mRevealParams != null) { + android.animation.Animator animator = mRevealParams.createCircularRevealAnimator(this); animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); animator.start(); + } else if (mIsFocusAnimationFlagActive && getVisibility() != VISIBLE) { + setAlpha(0f); + getFocusAnimator(crossFadeView).start(); } focus(); } @@ -737,6 +824,81 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mOnSendListeners.remove(listener); } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (mIsFocusAnimationFlagActive) setPivotY(getMeasuredHeight()); + if (mContentBackgroundBounds != null) { + mContentBackground.setBounds(mContentBackgroundBounds); + } + } + + private Animator getFocusAnimator(View crossFadeView) { + final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0f, 1f); + alphaAnimator.setStartDelay(FOCUS_ANIMATION_FADE_IN_DELAY); + alphaAnimator.setDuration(FOCUS_ANIMATION_FADE_IN_DURATION); + alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR); + + ValueAnimator scaleAnimator = ValueAnimator.ofFloat(FOCUS_ANIMATION_MIN_SCALE, 1f); + scaleAnimator.addUpdateListener(valueAnimator -> { + setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue()); + }); + scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION); + scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN); + + final Animator crossFadeViewAlphaAnimator = + ObjectAnimator.ofFloat(crossFadeView, View.ALPHA, 1f, 0f); + crossFadeViewAlphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION); + crossFadeViewAlphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR); + alphaAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation, boolean isReverse) { + crossFadeView.setAlpha(1f); + } + }); + + final AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(alphaAnimator, scaleAnimator, crossFadeViewAlphaAnimator); + return animatorSet; + } + + private Animator getDefocusAnimator() { + final Animator alphaAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 1f, 0f); + alphaAnimator.setDuration(FOCUS_ANIMATION_CROSSFADE_DURATION); + alphaAnimator.setInterpolator(InterpolatorsAndroidX.LINEAR); + + ValueAnimator scaleAnimator = ValueAnimator.ofFloat(1f, FOCUS_ANIMATION_MIN_SCALE); + scaleAnimator.addUpdateListener(valueAnimator -> { + setFocusAnimationScaleY((float) scaleAnimator.getAnimatedValue()); + }); + scaleAnimator.setDuration(FOCUS_ANIMATION_TOTAL_DURATION); + scaleAnimator.setInterpolator(InterpolatorsAndroidX.FAST_OUT_SLOW_IN); + scaleAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation, boolean isReverse) { + setFocusAnimationScaleY(1f); + } + }); + + final AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(alphaAnimator, scaleAnimator); + return animatorSet; + } + + /** + * Sets affected view properties for a vertical scale animation + * + * @param scaleY desired vertical view scale + */ + private void setFocusAnimationScaleY(float scaleY) { + int verticalBoundOffset = (int) ((1f - scaleY) * 0.5f * mContentView.getHeight()); + mContentBackgroundBounds = new Rect(0, verticalBoundOffset, mContentView.getWidth(), + mContentView.getHeight() - verticalBoundOffset); + mContentBackground.setBounds(mContentBackgroundBounds); + mContentView.setBackground(mContentBackground); + setTranslationY(verticalBoundOffset); + } + /** Handler for button click on send action in IME. */ private class EditorActionHandler implements TextView.OnEditorActionListener { @@ -991,11 +1153,11 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene this.radius = radius; } - Animator createCircularHideAnimator(View view) { + android.animation.Animator createCircularHideAnimator(View view) { return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0); } - Animator createCircularRevealAnimator(View view) { + android.animation.Animator createCircularRevealAnimator(View view) { return ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 0, radius); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt index f8451017b367..22b4c9d81d25 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt @@ -30,6 +30,8 @@ import android.util.Log import android.view.View import com.android.internal.logging.UiEventLogger import com.android.systemui.R +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags.NOTIFICATION_INLINE_REPLY_ANIMATION import com.android.systemui.statusbar.NotificationRemoteInputManager import com.android.systemui.statusbar.RemoteInputController import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -61,6 +63,8 @@ interface RemoteInputViewController { var revealParams: RevealParams? + val isFocusAnimationFlagActive: Boolean + /** * Sets the smart reply that should be inserted in the remote input, or `null` if the user is * not editing a smart reply. @@ -117,7 +121,8 @@ class RemoteInputViewControllerImpl @Inject constructor( private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler, private val remoteInputController: RemoteInputController, private val shortcutManager: ShortcutManager, - private val uiEventLogger: UiEventLogger + private val uiEventLogger: UiEventLogger, + private val mFlags: FeatureFlags ) : RemoteInputViewController { private val onSendListeners = ArraySet<OnSendRemoteInputListener>() @@ -149,6 +154,9 @@ class RemoteInputViewControllerImpl @Inject constructor( override val isActive: Boolean get() = view.isActive + override val isFocusAnimationFlagActive: Boolean + get() = mFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION) + override fun bind() { if (isBound) return isBound = true @@ -159,6 +167,7 @@ class RemoteInputViewControllerImpl @Inject constructor( view.setSupportedMimeTypes(it.allowedDataTypes) } view.setRevealParameters(revealParams) + view.setIsFocusAnimationFlagActive(isFocusAnimationFlagActive) view.addOnEditTextFocusChangedListener(onFocusChangeListener) view.addOnSendRemoteInputListener(onSendRemoteInputListener) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java index 915e999c2646..1fe2008d2abe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.policy; import static android.view.ContentInfo.SOURCE_CLIPBOARD; +import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD; + import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertEquals; @@ -57,6 +59,7 @@ import android.window.OnBackInvokedDispatcher; import android.window.WindowOnBackInvokedDispatcher; import androidx.annotation.NonNull; +import androidx.core.animation.AnimatorTestRule; import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; @@ -64,15 +67,19 @@ import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationTestHelper; +import com.android.systemui.statusbar.notification.stack.StackStateAnimator; import com.android.systemui.statusbar.phone.LightBarController; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -99,6 +106,9 @@ public class RemoteInputViewTest extends SysuiTestCase { private BlockingQueueIntentReceiver mReceiver; private final UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake(); + @ClassRule + public static AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(); + @Before public void setUp() throws Exception { allowTestableLooperAsMainThread(); @@ -294,6 +304,9 @@ public class RemoteInputViewTest extends SysuiTestCase { /* invoke the captured callback */ onBackInvokedCallbackCaptor.getValue().onBackInvoked(); + /* wait for RemoteInputView disappear animation to finish */ + mAnimatorTestRule.advanceTimeBy(StackStateAnimator.ANIMATION_DURATION_STANDARD); + /* verify that the RemoteInputView goes away */ assertEquals(view.getVisibility(), View.GONE); } @@ -363,19 +376,70 @@ public class RemoteInputViewTest extends SysuiTestCase { mUiEventLoggerFake.eventId(1)); } + @Test + public void testFocusAnimation() throws Exception { + NotificationTestHelper helper = new NotificationTestHelper( + mContext, + mDependency, + TestableLooper.get(this)); + ExpandableNotificationRow row = helper.createRow(); + RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); + bindController(view, row.getEntry()); + view.setVisibility(View.GONE); + + View crossFadeView = new View(mContext); + + // Start focus animation + view.focusAnimated(crossFadeView); + + // fast forward to end of animation + mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD); + + // assert that crossFadeView's alpha is reset to 1f after the animation (hidden behind + // RemoteInputView) + assertEquals(1f, crossFadeView.getAlpha()); + assertEquals(View.VISIBLE, view.getVisibility()); + assertEquals(1f, view.getAlpha()); + } + + @Test + public void testDefocusAnimation() throws Exception { + NotificationTestHelper helper = new NotificationTestHelper( + mContext, + mDependency, + TestableLooper.get(this)); + ExpandableNotificationRow row = helper.createRow(); + RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController); + bindController(view, row.getEntry()); + + // Start defocus animation + view.onDefocus(true, false); + assertEquals(View.VISIBLE, view.getVisibility()); + + // fast forward to end of animation + mAnimatorTestRule.advanceTimeBy(ANIMATION_DURATION_STANDARD); + + // assert that RemoteInputView is no longer visible + assertEquals(View.GONE, view.getVisibility()); + } + // NOTE: because we're refactoring the RemoteInputView and moving logic into the - // RemoteInputViewController, it's easiest to just test the system of the two classes together. + // RemoteInputViewController, it's easiest to just test the system of the two classes together. @NonNull private RemoteInputViewController bindController( RemoteInputView view, NotificationEntry entry) { + FakeFeatureFlags fakeFeatureFlags = new FakeFeatureFlags(); + fakeFeatureFlags.set(Flags.NOTIFICATION_INLINE_REPLY_ANIMATION, true); RemoteInputViewControllerImpl viewController = new RemoteInputViewControllerImpl( view, entry, mRemoteInputQuickSettingsDisabler, mController, mShortcutManager, - mUiEventLoggerFake); + mUiEventLoggerFake, + fakeFeatureFlags + ); viewController.bind(); return viewController; } |