summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt97
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java88
5 files changed, 211 insertions, 35 deletions
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
index 0d742cc6e382..9a17693dd75e 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
@@ -17,6 +17,7 @@
package com.android.wm.shell.bubbles.bar
import android.app.ActivityManager
+import android.content.ComponentName
import android.content.Context
import android.content.pm.ShortcutInfo
import android.graphics.Insets
@@ -24,6 +25,7 @@ import android.graphics.Rect
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
+import android.widget.FrameLayout
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -110,9 +112,9 @@ class BubbleBarExpandedViewTest {
regionSamplingProvider = TestRegionSamplingProvider()
- bubbleExpandedView = (inflater.inflate(
+ bubbleExpandedView = inflater.inflate(
R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */
- ) as BubbleBarExpandedView)
+ ) as BubbleBarExpandedView
bubbleExpandedView.initialize(
expandedViewManager,
positioner,
@@ -124,11 +126,11 @@ class BubbleBarExpandedViewTest {
regionSamplingProvider,
)
- getInstrumentation().runOnMainSync(Runnable {
+ getInstrumentation().runOnMainSync {
bubbleExpandedView.onAttachedToWindow()
// Helper should be created once attached to window
testableRegionSamplingHelper = regionSamplingProvider!!.helper
- })
+ }
bubble = Bubble(
"key",
@@ -254,6 +256,93 @@ class BubbleBarExpandedViewTest {
assertThat(uiEventLoggerFake.logs[0]).hasBubbleInfo(bubble)
}
+ @Test
+ fun animateExpansion_waitsUntilTaskCreated() {
+ var animated = false
+ bubbleExpandedView.animateExpansionWhenTaskViewVisible { animated = true }
+ assertThat(animated).isFalse()
+ bubbleExpandedView.onTaskCreated()
+ assertThat(animated).isTrue()
+ }
+
+ @Test
+ fun animateExpansion_taskViewAttachedAndVisible() {
+ val inflater = LayoutInflater.from(context)
+ val expandedView = inflater.inflate(
+ R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */
+ ) as BubbleBarExpandedView
+ val taskView = FakeBubbleTaskViewFactory().create()
+ val taskViewParent = FrameLayout(context)
+ taskViewParent.addView(taskView.taskView)
+ taskView.listener.onTaskCreated(666, ComponentName(context, "BubbleBarExpandedViewTest"))
+ assertThat(taskView.isVisible).isTrue()
+
+ expandedView.initialize(
+ expandedViewManager,
+ positioner,
+ BubbleLogger(uiEventLoggerFake),
+ false /* isOverflow */,
+ taskView,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingProvider,
+ )
+
+ // the task view should be removed from its parent
+ assertThat(taskView.taskView.parent).isNull()
+
+ var animated = false
+ expandedView.animateExpansionWhenTaskViewVisible { animated = true }
+ assertThat(animated).isFalse()
+
+ // send an invisible signal to simulate the surface getting destroyed
+ expandedView.onContentVisibilityChanged(false)
+
+ // send a visible signal to simulate a new surface getting created
+ expandedView.onContentVisibilityChanged(true)
+
+ assertThat(taskView.taskView.parent).isEqualTo(expandedView)
+ assertThat(animated).isTrue()
+ }
+
+ @Test
+ fun animateExpansion_taskViewAttachedAndInvisible() {
+ val inflater = LayoutInflater.from(context)
+ val expandedView = inflater.inflate(
+ R.layout.bubble_bar_expanded_view, null, false /* attachToRoot */
+ ) as BubbleBarExpandedView
+ val taskView = FakeBubbleTaskViewFactory().create()
+ val taskViewParent = FrameLayout(context)
+ taskViewParent.addView(taskView.taskView)
+ taskView.listener.onTaskCreated(666, ComponentName(context, "BubbleBarExpandedViewTest"))
+ assertThat(taskView.isVisible).isTrue()
+ taskView.listener.onTaskVisibilityChanged(666, false)
+ assertThat(taskView.isVisible).isFalse()
+
+ expandedView.initialize(
+ expandedViewManager,
+ positioner,
+ BubbleLogger(uiEventLoggerFake),
+ false /* isOverflow */,
+ taskView,
+ mainExecutor,
+ bgExecutor,
+ regionSamplingProvider,
+ )
+
+ // the task view should be added to the expanded view
+ assertThat(taskView.taskView.parent).isEqualTo(expandedView)
+
+ var animated = false
+ expandedView.animateExpansionWhenTaskViewVisible { animated = true }
+ assertThat(animated).isFalse()
+
+ // send a visible signal to simulate a new surface getting created
+ expandedView.onContentVisibilityChanged(true)
+
+ assertThat(animated).isTrue()
+ }
+
private fun BubbleBarExpandedView.menuView(): BubbleBarMenuView {
return findViewByPredicate { it is BubbleBarMenuView }
}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
index 00d9a931cebe..6fca79876f12 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
@@ -253,6 +253,7 @@ class BubbleBarLayerViewTest {
getInstrumentation().runOnMainSync {
bubbleBarLayerView.showExpandedView(bubble)
+ bubble.bubbleBarExpandedView!!.onContentVisibilityChanged(true)
}
waitForExpandedViewAnimation()
@@ -276,6 +277,7 @@ class BubbleBarLayerViewTest {
getInstrumentation().runOnMainSync {
bubbleBarLayerView.showExpandedView(bubble)
+ bubble.bubbleBarExpandedView!!.onContentVisibilityChanged(true)
}
waitForExpandedViewAnimation()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt
index 68fc0c99abee..a517a2d550b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt
@@ -42,6 +42,16 @@ class BubbleTaskView(val taskView: TaskView, executor: Executor) {
var componentName: ComponentName? = null
private set
+ /**
+ * Whether the task view is visible and has a surface. Note that this does not check the alpha
+ * value of the task view.
+ *
+ * When this is `true` it is safe to start showing the task view. Otherwise if this is `false`
+ * callers should wait for it to be visible which will be indicated either by a call to
+ * [TaskView.Listener.onTaskCreated] or [TaskView.Listener.onTaskVisibilityChanged]. */
+ var isVisible = false
+ private set
+
/** [TaskView.Listener] for users of this class. */
var delegateListener: TaskView.Listener? = null
@@ -61,9 +71,12 @@ class BubbleTaskView(val taskView: TaskView, executor: Executor) {
this@BubbleTaskView.taskId = taskId
isCreated = true
componentName = name
+ // when the task is created it is visible
+ isVisible = true
}
override fun onTaskVisibilityChanged(taskId: Int, visible: Boolean) {
+ this@BubbleTaskView.isVisible = visible
delegateListener?.onTaskVisibilityChanged(taskId, visible)
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 74c3748dccaf..a313bd004a51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -161,6 +161,7 @@ public class BubbleBarAnimationHelper {
updateExpandedView();
bbev.setAnimating(true);
+ bbev.setSurfaceZOrderedOnTop(true);
bbev.setContentVisibility(false);
bbev.setAlpha(0f);
bbev.setTaskViewAlpha(0f);
@@ -171,28 +172,29 @@ public class BubbleBarAnimationHelper {
bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
- mExpandedViewAlphaAnimator.start();
-
- PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
- PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
- .spring(AnimatableScaleMatrix.SCALE_X,
- AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
- mScaleInSpringConfig)
- .spring(AnimatableScaleMatrix.SCALE_Y,
- AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
- mScaleInSpringConfig)
- .addUpdateListener((target, values) -> {
- bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
- })
- .withEndActions(() -> {
- bbev.setAnimationMatrix(null);
- updateExpandedView();
- bbev.setSurfaceZOrderedOnTop(false);
- if (afterAnimation != null) {
- afterAnimation.run();
- }
- })
- .start();
+ bbev.animateExpansionWhenTaskViewVisible(() -> {
+ mExpandedViewAlphaAnimator.start();
+
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix).cancel();
+ PhysicsAnimator.getInstance(mExpandedViewContainerMatrix)
+ .spring(AnimatableScaleMatrix.SCALE_X,
+ AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
+ mScaleInSpringConfig)
+ .spring(AnimatableScaleMatrix.SCALE_Y,
+ AnimatableScaleMatrix.getAnimatableValueForScaleFactor(1f),
+ mScaleInSpringConfig)
+ .addUpdateListener((target, values) -> {
+ bbev.setAnimationMatrix(mExpandedViewContainerMatrix);
+ })
+ .withEndActions(() -> {
+ bbev.setAnimationMatrix(null);
+ updateExpandedView();
+ if (afterAnimation != null) {
+ afterAnimation.run();
+ }
+ })
+ .start();
+ });
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index 272dfecb0bf9..e1dabdcc7f9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -131,6 +131,11 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
/** Current corner radius */
private float mCurrentCornerRadius = 0f;
+ /** A runnable to start the expansion animation as soon as the task view is made visible. */
+ @Nullable
+ private Runnable mAnimateExpansion = null;
+ private TaskViewVisibilityState mVisibilityState = TaskViewVisibilityState.INVISIBLE;
+
/**
* Whether we want the {@code TaskView}'s content to be visible (alpha = 1f). If
* {@link #mIsAnimating} is true, this may not reflect the {@code TaskView}'s actual alpha
@@ -140,6 +145,18 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
private boolean mIsAnimating;
private boolean mIsDragging;
+ /** An enum value that tracks the visibility state of the task view */
+ private enum TaskViewVisibilityState {
+ /** The task view is going away, and we're waiting for the surface to be destroyed. */
+ PENDING_INVISIBLE,
+ /** The task view is invisible and does not have a surface. */
+ INVISIBLE,
+ /** The task view is in the process of being added to a surface. */
+ PENDING_VISIBLE,
+ /** The task view is visible and has a surface. */
+ VISIBLE
+ }
+
public BubbleBarExpandedView(Context context) {
this(context, null);
}
@@ -206,16 +223,27 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, expandedViewManager,
/* listener= */ this, bubbleTaskView,
/* viewParent= */ this);
+
+ // if the task view is already attached to a parent we need to remove it
if (mTaskView.getParent() != null) {
+ // it's possible that the task view is visible, e.g. if we're unfolding, in which
+ // case removing it will trigger a visibility change. we have to wait for that
+ // signal before we can add it to this expanded view, otherwise the signal will be
+ // incorrect because the task view will have a surface.
+ // if the task view is not visible, then it has no surface and removing it will not
+ // trigger any visibility change signals.
+ if (bubbleTaskView.isVisible()) {
+ mVisibilityState = TaskViewVisibilityState.PENDING_INVISIBLE;
+ }
((ViewGroup) mTaskView.getParent()).removeView(mTaskView);
}
- FrameLayout.LayoutParams lp =
- new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
- addView(mTaskView, lp);
- mTaskView.setEnableSurfaceClipping(true);
- mTaskView.setCornerRadius(mCurrentCornerRadius);
- mTaskView.setVisibility(VISIBLE);
- mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
+
+ // if we're invisible it's safe to setup the task view and then await on the visibility
+ // signal.
+ if (mVisibilityState == TaskViewVisibilityState.INVISIBLE) {
+ mVisibilityState = TaskViewVisibilityState.PENDING_VISIBLE;
+ setupTaskView();
+ }
// Handle view needs to draw on top of task view.
bringChildToFront(mHandleView);
@@ -269,6 +297,16 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
});
}
+ private void setupTaskView() {
+ FrameLayout.LayoutParams lp =
+ new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+ addView(mTaskView, lp);
+ mTaskView.setEnableSurfaceClipping(true);
+ mTaskView.setCornerRadius(mCurrentCornerRadius);
+ mTaskView.setVisibility(VISIBLE);
+ mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
+ }
+
public BubbleBarHandleView getHandleView() {
return mHandleView;
}
@@ -326,15 +364,28 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
@Override
public void onTaskCreated() {
- setContentVisibility(true);
+ if (mTaskView != null) {
+ mTaskView.setAlpha(0);
+ }
if (mListener != null) {
mListener.onTaskCreated();
}
+ // when the task is created we're visible
+ onTaskViewVisible();
}
@Override
public void onContentVisibilityChanged(boolean visible) {
- setContentVisibility(visible);
+ if (mVisibilityState == TaskViewVisibilityState.PENDING_INVISIBLE && !visible) {
+ // the surface is now destroyed. set up the task view and wait for the visibility
+ // signal.
+ mVisibilityState = TaskViewVisibilityState.PENDING_VISIBLE;
+ setupTaskView();
+ return;
+ }
+ if (visible) {
+ onTaskViewVisible();
+ }
}
@Override
@@ -350,6 +401,25 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
mListener.onBackPressed();
}
+ void animateExpansionWhenTaskViewVisible(Runnable animateExpansion) {
+ if (mVisibilityState == TaskViewVisibilityState.VISIBLE) {
+ animateExpansion.run();
+ } else {
+ mAnimateExpansion = animateExpansion;
+ }
+ }
+
+ private void onTaskViewVisible() {
+ // if we're waiting to be visible, start the expansion animation if it's pending.
+ if (mVisibilityState == TaskViewVisibilityState.PENDING_VISIBLE) {
+ mVisibilityState = TaskViewVisibilityState.VISIBLE;
+ if (mAnimateExpansion != null) {
+ mAnimateExpansion.run();
+ mAnimateExpansion = null;
+ }
+ }
+ }
+
/**
* Set whether this view is currently being dragged.
*