diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 09601970e96a5..e068962130c91 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -79,6 +79,11 @@ object Flags { // TODO(b/257315550): Tracking Bug val NO_HUN_FOR_OLD_WHEN = releasedFlag(118, "no_hun_for_old_when") + // TODO(b/260335638): Tracking Bug + @JvmField + val NOTIFICATION_INLINE_REPLY_ANIMATION = + unreleasedFlag(174148361, "notification_inline_reply_animation") + /** Makes sure notification panel is updated before the user switch is complete. */ // TODO(b/278873737): Tracking Bug @JvmField diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java index 38bbb351a1314..bdb206beb123a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.inflation; +import static com.android.systemui.flags.Flags.NOTIFICATION_INLINE_REPLY_ANIMATION; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC; @@ -30,6 +31,7 @@ import android.view.ViewGroup; import com.android.internal.util.NotificationMessagingUtil; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.flags.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -71,6 +73,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { private NotificationListContainer mListContainer; private BindRowCallback mBindRowCallback; private NotificationClicker mNotificationClicker; + private FeatureFlags mFeatureFlags; @Inject public NotificationRowBinderImpl( @@ -82,7 +85,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { RowContentBindStage rowContentBindStage, Provider rowInflaterTaskProvider, ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder, - IconManager iconManager) { + IconManager iconManager, + FeatureFlags featureFlags) { mContext = context; mNotifBindPipeline = notifBindPipeline; mRowContentBindStage = rowContentBindStage; @@ -92,6 +96,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { mRowInflaterTaskProvider = rowInflaterTaskProvider; mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder; mIconManager = iconManager; + mFeatureFlags = featureFlags; } /** @@ -175,6 +180,8 @@ public class NotificationRowBinderImpl implements NotificationRowBinder { entry.setRow(row); mNotifBindPipeline.manageRow(entry, row); mBindRowCallback.onBindRow(row); + row.setInlineReplyAnimationFlagEnabled( + mFeatureFlags.isEnabled(NOTIFICATION_INLINE_REPLY_ANIMATION)); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index ba8a5f3de45c8..bfb6fb0fcdc76 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -271,6 +271,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private OnExpandClickListener mOnExpandClickListener; private View.OnClickListener mOnFeedbackClickListener; private Path mExpandingClipPath; + private boolean mIsInlineReplyAnimationFlagEnabled = false; // Listener will be called when receiving a long click event. // Use #setLongPressPosition to optionally assign positional data with the long press. @@ -3054,6 +3055,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return showingLayout != null && showingLayout.requireRowToHaveOverlappingRendering(); } + public void setInlineReplyAnimationFlagEnabled(boolean isEnabled) { + mIsInlineReplyAnimationFlagEnabled = isEnabled; + } + @Override public void setActualHeight(int height, boolean notifyListeners) { boolean changed = height != getActualHeight(); @@ -3073,7 +3078,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } int contentHeight = Math.max(getMinHeight(), height); for (NotificationContentView l : mLayouts) { - l.setContentHeight(height); + if (mIsInlineReplyAnimationFlagEnabled) { + l.setContentHeight(height); + } else { + l.setContentHeight(contentHeight); + } } if (mIsSummaryWithChildren) { mChildrenContainer.setActualHeight(height); 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 f432af2232a9f..451d837b63a0a 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 @@ -635,7 +635,8 @@ public class NotificationContentView extends FrameLayout implements Notification int hint; if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) { hint = getViewHeight(VISIBLE_TYPE_HEADSUP); - if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isAnimatingAppearance()) { + if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isAnimatingAppearance() + && mHeadsUpRemoteInputController.isFocusAnimationFlagActive()) { // While the RemoteInputView is animating its appearance, it should be allowed // to overlap the hint, therefore no space is reserved for the hint during the // appearance animation of the RemoteInputView 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 e311bad9e865a..d585163aa2238 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -21,6 +21,7 @@ import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_STANDARD; import android.app.ActivityManager; +import android.app.Notification; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.ColorStateList; @@ -134,6 +135,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene @Nullable private RevealParams mRevealParams; private Rect mContentBackgroundBounds; + private boolean mIsFocusAnimationFlagActive; private boolean mIsAnimatingAppearance = false; // TODO(b/193539698): move these to a Controller @@ -431,7 +433,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene // case to prevent flicker. if (!mRemoved) { ViewGroup parent = (ViewGroup) getParent(); - if (animate && parent != null) { + if (animate && parent != null && mIsFocusAnimationFlagActive) { ViewGroup grandParent = (ViewGroup) parent.getParent(); ViewGroupOverlay overlay = parent.getOverlay(); @@ -595,11 +597,25 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setText(editTextContent); } + /** + * Sets whether the feature flag for the revised inline reply animation is active or not. + * @param active + */ + public void setIsFocusAnimationFlagActive(boolean active) { + mIsFocusAnimationFlagActive = active; + } + /** * Focuses the RemoteInputView and animates its appearance */ public void focusAnimated() { - if (getVisibility() != VISIBLE) { + 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) { mIsAnimatingAppearance = true; setAlpha(0f); Animator focusAnimator = getFocusAnimator(getActionsContainerLayout()); @@ -654,19 +670,37 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene } private void reset() { - mProgressBar.setVisibility(INVISIBLE); + if (mIsFocusAnimationFlagActive) { + mProgressBar.setVisibility(INVISIBLE); + mResetting = true; + mSending = false; + onDefocus(true /* animate */, false /* logClose */, () -> { + mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText()); + mEditText.getText().clear(); + mEditText.setEnabled(isAggregatedVisible()); + mSendButton.setVisibility(VISIBLE); + mController.removeSpinning(mEntry.getKey(), mToken); + updateSendButton(); + setAttachment(null); + mResetting = false; + }); + return; + } + mResetting = true; mSending = false; - onDefocus(true /* animate */, false /* logClose */, () -> { - mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText()); - mEditText.getText().clear(); - mEditText.setEnabled(isAggregatedVisible()); - mSendButton.setVisibility(VISIBLE); - mController.removeSpinning(mEntry.getKey(), mToken); - updateSendButton(); - setAttachment(null); - mResetting = false; - }); + mEntry.remoteInputTextWhenReset = SpannedString.valueOf(mEditText.getText()); + + mEditText.getText().clear(); + mEditText.setEnabled(isAggregatedVisible()); + mSendButton.setVisibility(VISIBLE); + mProgressBar.setVisibility(INVISIBLE); + mController.removeSpinning(mEntry.getKey(), mToken); + updateSendButton(); + onDefocus(false /* animate */, false /* logClose */, null /* doAfterDefocus */); + setAttachment(null); + + mResetting = false; } @Override @@ -810,7 +844,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); - setPivotY(getMeasuredHeight()); + if (mIsFocusAnimationFlagActive) setPivotY(getMeasuredHeight()); if (mContentBackgroundBounds != null) { mContentBackground.setBounds(mContentBackgroundBounds); } 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 e9b1d543be260..22b4c9d81d256 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. @@ -118,6 +122,7 @@ class RemoteInputViewControllerImpl @Inject constructor( private val remoteInputController: RemoteInputController, private val shortcutManager: ShortcutManager, private val uiEventLogger: UiEventLogger, + private val mFlags: FeatureFlags ) : RemoteInputViewController { private val onSendListeners = ArraySet() @@ -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 50bb0584aa4cc..391c8ca4d286f 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 @@ -70,6 +70,8 @@ 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; @@ -451,13 +453,17 @@ public class RemoteInputViewTest extends SysuiTestCase { 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; }