summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java40
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java25
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java3
6 files changed, 96 insertions, 6 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index b5a575499a3a..922472a26113 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -59,6 +59,8 @@ import java.util.concurrent.Executor;
public class Bubble implements BubbleViewProvider {
private static final String TAG = "Bubble";
+ public static final String KEY_APP_BUBBLE = "key_app_bubble";
+
private final String mKey;
@Nullable
private final String mGroupKey;
@@ -164,6 +166,14 @@ public class Bubble implements BubbleViewProvider {
private PendingIntent mDeleteIntent;
/**
+ * Used only for a special bubble in the stack that has the key {@link #KEY_APP_BUBBLE}.
+ * There can only be one of these bubbles in the stack and this intent will be populated for
+ * that bubble.
+ */
+ @Nullable
+ private Intent mAppIntent;
+
+ /**
* Create a bubble with limited information based on given {@link ShortcutInfo}.
* Note: Currently this is only being used when the bubble is persisted to disk.
*/
@@ -192,6 +202,22 @@ public class Bubble implements BubbleViewProvider {
mBubbleMetadataFlagListener = listener;
}
+ public Bubble(Intent intent,
+ UserHandle user,
+ Executor mainExecutor) {
+ mKey = KEY_APP_BUBBLE;
+ mGroupKey = null;
+ mLocusId = null;
+ mFlags = 0;
+ mUser = user;
+ mShowBubbleUpdateDot = false;
+ mMainExecutor = mainExecutor;
+ mTaskId = INVALID_TASK_ID;
+ mAppIntent = intent;
+ mDesiredHeight = Integer.MAX_VALUE;
+ mPackageName = intent.getPackage();
+ }
+
@VisibleForTesting(visibility = PRIVATE)
public Bubble(@NonNull final BubbleEntry entry,
final Bubbles.BubbleMetadataFlagListener listener,
@@ -417,6 +443,9 @@ public class Bubble implements BubbleViewProvider {
mShortcutInfo = info.shortcutInfo;
mAppName = info.appName;
+ if (mTitle == null) {
+ mTitle = mAppName;
+ }
mFlyoutMessage = info.flyoutMessage;
mBadgeBitmap = info.badgeBitmap;
@@ -520,7 +549,7 @@ public class Bubble implements BubbleViewProvider {
* @return the last time this bubble was updated or accessed, whichever is most recent.
*/
long getLastActivity() {
- return Math.max(mLastUpdated, mLastAccessed);
+ return isAppBubble() ? Long.MAX_VALUE : Math.max(mLastUpdated, mLastAccessed);
}
/**
@@ -719,6 +748,15 @@ public class Bubble implements BubbleViewProvider {
return mDeleteIntent;
}
+ @Nullable
+ Intent getAppBubbleIntent() {
+ return mAppIntent;
+ }
+
+ boolean isAppBubble() {
+ return KEY_APP_BUBBLE.equals(mKey);
+ }
+
Intent getSettingsIntent(final Context context) {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 0dfba3464f23..93413dbe7e5f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1017,6 +1017,20 @@ public class BubbleController implements ConfigurationChangeListener {
}
/**
+ * Adds a bubble for a specific intent. These bubbles are <b>not</b> backed by a notification
+ * and remain until the user dismisses the bubble or bubble stack. Only one intent bubble
+ * is supported at a time.
+ *
+ * @param intent the intent to display in the bubble expanded view.
+ */
+ public void addAppBubble(Intent intent) {
+ if (intent == null || intent.getPackage() == null) return;
+ Bubble b = new Bubble(intent, UserHandle.of(mCurrentUserId), mMainExecutor);
+ b.setShouldAutoExpand(true);
+ inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
+ }
+
+ /**
* Fills the overflow bubbles by loading them from disk.
*/
void loadOverflowBubblesFromDisk() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 840b2856270c..06f232cb7489 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -224,15 +224,23 @@ public class BubbleExpandedView extends LinearLayout {
try {
options.setTaskAlwaysOnTop(true);
options.setLaunchedFromBubble(true);
- if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
+
+ Intent fillInIntent = new Intent();
+ // Apply flags to make behaviour match documentLaunchMode=always.
+ fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
+ fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
+
+ if (mBubble.isAppBubble()) {
+ PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+ mBubble.getAppBubbleIntent(),
+ PendingIntent.FLAG_MUTABLE,
+ null);
+ mTaskView.startActivity(pi, fillInIntent, options, launchBounds);
+ } else if (!mIsOverflow && mBubble.hasMetadataShortcutId()) {
options.setApplyActivityFlagsForBubbles(true);
mTaskView.startShortcutActivity(mBubble.getShortcutInfo(),
options, launchBounds);
} else {
- Intent fillInIntent = new Intent();
- // Apply flags to make behaviour match documentLaunchMode=always.
- fillInIntent.addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
- fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
if (mBubble != null) {
mBubble.setIntentActive();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index c9d523c779ea..33074de8f583 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -591,6 +591,7 @@ public abstract class WMShellBaseModule {
ShellInit shellInit,
ShellController shellController,
ShellCommandHandler shellCommandHandler,
+ Optional<BubbleController> bubbleController,
WindowManager windowManager,
ShellTaskOrganizer organizer,
TaskViewTransitions taskViewTransitions,
@@ -602,6 +603,7 @@ public abstract class WMShellBaseModule {
shellInit,
shellController,
shellCommandHandler,
+ bubbleController,
windowManager,
organizer,
taskViewTransitions,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java
index c79b9b8cc443..67552991869b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/floating/FloatingTasksController.java
@@ -39,6 +39,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskViewTransitions;
+import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
@@ -54,6 +55,7 @@ import com.android.wm.shell.sysui.ShellInit;
import java.io.PrintWriter;
import java.util.Objects;
+import java.util.Optional;
/**
* Entry point for creating and managing floating tasks.
@@ -70,6 +72,8 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
public static final boolean FLOATING_TASKS_ENABLED =
SystemProperties.getBoolean("persist.wm.debug.floating_tasks", false);
+ public static final boolean SHOW_FLOATING_TASKS_AS_BUBBLES =
+ SystemProperties.getBoolean("persist.wm.debug.floating_tasks_as_bubbles", false);
@VisibleForTesting
static final int SMALLEST_SCREEN_WIDTH_DP_TO_BE_TABLET = 600;
@@ -82,6 +86,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
private Context mContext;
private ShellController mShellController;
private ShellCommandHandler mShellCommandHandler;
+ private @Nullable BubbleController mBubbleController;
private WindowManager mWindowManager;
private ShellTaskOrganizer mTaskOrganizer;
private TaskViewTransitions mTaskViewTransitions;
@@ -111,6 +116,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
ShellInit shellInit,
ShellController shellController,
ShellCommandHandler shellCommandHandler,
+ Optional<BubbleController> bubbleController,
WindowManager windowManager,
ShellTaskOrganizer organizer,
TaskViewTransitions transitions,
@@ -120,6 +126,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
mContext = context;
mShellController = shellController;
mShellCommandHandler = shellCommandHandler;
+ mBubbleController = bubbleController.get();
mWindowManager = windowManager;
mTaskOrganizer = organizer;
mTaskViewTransitions = transitions;
@@ -187,6 +194,22 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
return true;
}
+ /** Returns true if the task was or should be shown as a bubble. */
+ private boolean maybeShowTaskAsBubble(Intent intent) {
+ if (SHOW_FLOATING_TASKS_AS_BUBBLES && mBubbleController != null) {
+ removeFloatingLayer();
+ if (intent.getPackage() != null) {
+ mBubbleController.addAppBubble(intent);
+ ProtoLog.d(WM_SHELL_FLOATING_APPS, "showing floating task as bubble: %s", intent);
+ } else {
+ ProtoLog.d(WM_SHELL_FLOATING_APPS,
+ "failed to show floating task as bubble: %s; unknown package", intent);
+ }
+ return true;
+ }
+ return false;
+ }
+
/**
* Shows, stashes, or un-stashes the floating task depending on state:
* - If there is no floating task for this intent, it shows this the provided task.
@@ -195,6 +218,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
*/
public void showOrSetStashed(Intent intent) {
if (!canShowTask(intent)) return;
+ if (maybeShowTaskAsBubble(intent)) return;
addFloatingLayer();
@@ -215,6 +239,7 @@ public class FloatingTasksController implements RemoteCallable<FloatingTasksCont
*/
public void showTask(Intent intent) {
if (!canShowTask(intent)) return;
+ if (maybeShowTaskAsBubble(intent)) return;
addFloatingLayer();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java
index f1b4311e5aa5..a88c83779f25 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/floating/FloatingTasksControllerTest.java
@@ -62,6 +62,8 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
/**
* Tests for the floating tasks controller.
*/
@@ -123,6 +125,7 @@ public class FloatingTasksControllerTest extends ShellTestCase {
mShellInit,
mShellController,
mock(ShellCommandHandler.class),
+ Optional.empty(),
mWindowManager,
mTaskOrganizer,
mock(TaskViewTransitions.class),