Handle process die event of a bubble activity gracefully.
When the process behind a bubble activity died (e.g. killed by lmkd,
or app crash), collapse the bubble and restart the activity when it's
expanded next time.
Bug: 126945401
Test: atest TaskStackChangedListenerTest
Change-Id: Ia2ee21f9ced51fe33756b1e12159f445d6ed083d
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 573a066..5d61179 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -762,6 +762,20 @@
expandedBubble.setContentVisibility(true);
}
}
+
+ @Override
+ public void onSingleTaskDisplayEmpty(int displayId) {
+ final Bubble expandedBubble = getExpandedBubble(mContext);
+ if (expandedBubble == null) {
+ return;
+ }
+ if (expandedBubble.getDisplayId() == displayId) {
+ mBubbleData.setExpanded(false);
+ }
+ if (expandedBubble.expandedView != null) {
+ expandedBubble.expandedView.notifyDisplayEmpty();
+ }
+ }
}
private static boolean areBubblesEnabled(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 0a19ac3..8c09913 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -63,6 +63,17 @@
public class BubbleExpandedView extends LinearLayout implements View.OnClickListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleExpandedView" : TAG_BUBBLES;
+ private enum ActivityViewStatus {
+ // ActivityView is being initialized, cannot start an activity yet.
+ INITIALIZING,
+ // ActivityView is initialized, and ready to start an activity.
+ INITIALIZED,
+ // Activity runs in the ActivityView.
+ ACTIVITY_STARTED,
+ // ActivityView is released, so activity launching will no longer be permitted.
+ RELEASED,
+ }
+
// The triangle pointing to the expanded view
private View mPointerView;
private int mPointerMargin;
@@ -72,7 +83,7 @@
// Views for expanded state
private ActivityView mActivityView;
- private boolean mActivityViewReady = false;
+ private ActivityViewStatus mActivityViewStatus = ActivityViewStatus.INITIALIZING;
private int mTaskId = -1;
private PendingIntent mBubbleIntent;
@@ -98,19 +109,21 @@
private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() {
@Override
public void onActivityViewReady(ActivityView view) {
- if (!mActivityViewReady) {
- mActivityViewReady = true;
- // Custom options so there is no activity transition animation
- ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
- 0 /* enterResId */, 0 /* exitResId */);
- // Post to keep the lifecycle normal
- post(() -> mActivityView.startActivity(mBubbleIntent, options));
+ switch (mActivityViewStatus) {
+ case INITIALIZING:
+ case INITIALIZED:
+ // Custom options so there is no activity transition animation
+ ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(),
+ 0 /* enterResId */, 0 /* exitResId */);
+ // Post to keep the lifecycle normal
+ post(() -> mActivityView.startActivity(mBubbleIntent, options));
+ mActivityViewStatus = ActivityViewStatus.ACTIVITY_STARTED;
}
}
@Override
public void onActivityViewDestroyed(ActivityView view) {
- mActivityViewReady = false;
+ mActivityViewStatus = ActivityViewStatus.RELEASED;
}
@Override
@@ -433,8 +446,10 @@
if (mActivityView == null) {
return;
}
- if (mActivityViewReady) {
- mActivityView.release();
+ switch (mActivityViewStatus) {
+ case INITIALIZED:
+ case ACTIVITY_STARTED:
+ mActivityView.release();
}
if (mTaskId != -1) {
try {
@@ -447,7 +462,16 @@
removeView(mActivityView);
mActivityView = null;
- mActivityViewReady = false;
+ }
+
+ /**
+ * Called when the last task is removed from a {@link android.hardware.display.VirtualDisplay}
+ * which {@link ActivityView} uses.
+ */
+ void notifyDisplayEmpty() {
+ if (mActivityViewStatus == ActivityViewStatus.ACTIVITY_STARTED) {
+ mActivityViewStatus = ActivityViewStatus.INITIALIZED;
+ }
}
private boolean usingActivityView() {