summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Liran Binyamin <liranb@google.com> 2023-06-13 16:38:57 -0400
committer Liran Binyamin <liranb@google.com> 2023-06-20 10:21:33 -0400
commit815722a7e5b10fc02d4c725518111ba6180578ea (patch)
treea331f809355af622b97934cb97df7da093e5c7ed
parent4b3863dfe74af6ec32515706fea7f2d4a7a27ddd (diff)
Support switching navigation modes.
Switching navigation modes in Settings updates how bubbles are displayed. Existing bubbles are re-added to the appropriate view. Bug: 269670598 Test: In Settings go to Display and Navigation mode and switch between Gesture and 3-button modes after creating bubbles. Change-Id: I7562040ce907907325a00bac041b2eb3923d4848
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java120
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt32
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java216
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java10
12 files changed, 406 insertions, 107 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 504839fedf06..7e09c989e1b3 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
@@ -422,6 +422,7 @@ public class Bubble implements BubbleViewProvider {
}
if (mBubbleBarExpandedView != null) {
mBubbleBarExpandedView.cleanUpExpandedState();
+ mBubbleBarExpandedView = null;
}
if (mIntent != null) {
mIntent.unregisterCancelListener(mIntentCancelListener);
@@ -549,10 +550,10 @@ public class Bubble implements BubbleViewProvider {
/**
* Set visibility of bubble in the expanded state.
*
- * @param visibility {@code true} if the expanded bubble should be visible on the screen.
- *
- * Note that this contents visibility doesn't affect visibility at {@link android.view.View},
+ * <p>Note that this contents visibility doesn't affect visibility at {@link android.view.View},
* and setting {@code false} actually means rendering the expanded view in transparent.
+ *
+ * @param visibility {@code true} if the expanded bubble should be visible on the screen.
*/
@Override
public void setTaskViewVisibility(boolean visibility) {
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 c48f2fdaf42f..796a98f51981 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
@@ -64,7 +64,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.NotificationListenerService;
@@ -92,6 +91,7 @@ import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+import com.android.wm.shell.bubbles.properties.BubbleProperties;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -143,16 +143,6 @@ public class BubbleController implements ConfigurationChangeListener,
private static final String SYSTEM_DIALOG_REASON_KEY = "reason";
private static final String SYSTEM_DIALOG_REASON_GESTURE_NAV = "gestureNav";
- // TODO(b/256873975) Should use proper flag when available to shell/launcher
- /**
- * Whether bubbles are showing in the bubble bar from launcher. This is only available
- * on large screens and {@link BubbleController#isShowingAsBubbleBar()} should be used
- * to check all conditions that indicate if the bubble bar is in use.
- */
- private static final boolean BUBBLE_BAR_ENABLED =
- SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false);
-
-
/**
* Common interface to send updates to bubble views.
*/
@@ -195,6 +185,7 @@ public class BubbleController implements ConfigurationChangeListener,
private final ShellController mShellController;
private final ShellCommandHandler mShellCommandHandler;
private final IWindowManager mWmService;
+ private final BubbleProperties mBubbleProperties;
// Used to post to main UI thread
private final ShellExecutor mMainExecutor;
@@ -291,7 +282,8 @@ public class BubbleController implements ConfigurationChangeListener,
@ShellBackgroundThread ShellExecutor bgExecutor,
TaskViewTransitions taskViewTransitions,
SyncTransactionQueue syncQueue,
- IWindowManager wmService) {
+ IWindowManager wmService,
+ BubbleProperties bubbleProperties) {
mContext = context;
mShellCommandHandler = shellCommandHandler;
mShellController = shellController;
@@ -328,6 +320,7 @@ public class BubbleController implements ConfigurationChangeListener,
mDragAndDropController = dragAndDropController;
mSyncQueue = syncQueue;
mWmService = wmService;
+ mBubbleProperties = bubbleProperties;
shellInit.addInitCallback(this::onInit, this);
}
@@ -518,11 +511,14 @@ public class BubbleController implements ConfigurationChangeListener,
/**
* Sets a listener to be notified of bubble updates. This is used by launcher so that
* it may render bubbles in itself. Only one listener is supported.
+ *
+ * <p>If bubble bar is supported, bubble views will be updated to switch to bar mode.
*/
public void registerBubbleStateListener(Bubbles.BubbleStateListener listener) {
- if (isShowingAsBubbleBar()) {
- // Only set the listener if bubble bar is showing.
+ if (canShowAsBubbleBar() && listener != null) {
+ // Only set the listener if we can show the bubble bar.
mBubbleStateListener = listener;
+ setUpBubbleViewsForMode();
sendInitialListenerUpdate();
} else {
mBubbleStateListener = null;
@@ -531,9 +527,15 @@ public class BubbleController implements ConfigurationChangeListener,
/**
* Unregisters the {@link Bubbles.BubbleStateListener}.
+ *
+ * <p>If there's an existing listener, then we're switching back to stack mode and bubble views
+ * will be updated accordingly.
*/
public void unregisterBubbleStateListener() {
- mBubbleStateListener = null;
+ if (mBubbleStateListener != null) {
+ mBubbleStateListener = null;
+ setUpBubbleViewsForMode();
+ }
}
/**
@@ -645,8 +647,12 @@ public class BubbleController implements ConfigurationChangeListener,
/** Whether bubbles are showing in the bubble bar. */
public boolean isShowingAsBubbleBar() {
- // TODO(b/269670598): should also check that we're in gesture nav
- return BUBBLE_BAR_ENABLED && mBubblePositioner.isLargeScreen();
+ return canShowAsBubbleBar() && mBubbleStateListener != null;
+ }
+
+ /** Whether the current configuration supports showing as bubble bar. */
+ private boolean canShowAsBubbleBar() {
+ return mBubbleProperties.isBubbleBarEnabled() && mBubblePositioner.isLargeScreen();
}
/** Whether this userId belongs to the current user. */
@@ -779,7 +785,7 @@ public class BubbleController implements ConfigurationChangeListener,
if (isShowingAsBubbleBar()) {
mWindowManager.addView(mLayerView, mWmLayoutParams);
mLayerView.setOnApplyWindowInsetsListener((view, windowInsets) -> {
- if (!windowInsets.equals(mWindowInsets)) {
+ if (!windowInsets.equals(mWindowInsets) && mLayerView != null) {
mWindowInsets = windowInsets;
mBubblePositioner.update();
mLayerView.onDisplaySizeChanged();
@@ -789,7 +795,7 @@ public class BubbleController implements ConfigurationChangeListener,
} else {
mWindowManager.addView(mStackView, mWmLayoutParams);
mStackView.setOnApplyWindowInsetsListener((view, windowInsets) -> {
- if (!windowInsets.equals(mWindowInsets)) {
+ if (!windowInsets.equals(mWindowInsets) && mStackView != null) {
mWindowInsets = windowInsets;
mBubblePositioner.update();
mStackView.onDisplaySizeChanged();
@@ -1066,9 +1072,11 @@ public class BubbleController implements ConfigurationChangeListener,
* Expands and selects the provided bubble as long as it already exists in the stack or the
* overflow.
*
- * This is used by external callers (launcher).
+ * <p>This is used by external callers (launcher).
*/
- public void expandStackAndSelectBubbleFromLauncher(String key) {
+ @VisibleForTesting
+ public void expandStackAndSelectBubbleFromLauncher(String key, boolean onLauncherHome) {
+ mBubblePositioner.setShowingInBubbleBar(onLauncherHome);
Bubble b = mBubbleData.getAnyBubbleWithkey(key);
if (b == null) {
return;
@@ -1286,6 +1294,50 @@ public class BubbleController implements ConfigurationChangeListener,
});
}
+ void setUpBubbleViewsForMode() {
+ mBubbleViewCallback = isShowingAsBubbleBar()
+ ? mBubbleBarViewCallback
+ : mBubbleStackViewCallback;
+
+ // reset the overflow so that it can be re-added later if needed.
+ if (mStackView != null) {
+ mStackView.resetOverflowView();
+ mStackView.removeAllViews();
+ }
+ // cleanup existing bubble views so they can be recreated later if needed.
+ mBubbleData.getBubbles().forEach(Bubble::cleanupViews);
+
+ // remove the current bubble container from window manager, null it out, and create a new
+ // container based on the current mode.
+ removeFromWindowManagerMaybe();
+ mLayerView = null;
+ mStackView = null;
+ ensureBubbleViewsAndWindowCreated();
+
+ // inflate bubble views
+ BubbleViewInfoTask.Callback callback = null;
+ if (!isShowingAsBubbleBar()) {
+ callback = b -> {
+ if (mStackView != null) {
+ mStackView.addBubble(b);
+ mStackView.setSelectedBubble(b);
+ } else {
+ Log.w(TAG, "Tried to add a bubble to the stack but the stack is null");
+ }
+ };
+ }
+ for (int i = mBubbleData.getBubbles().size() - 1; i >= 0; i--) {
+ Bubble bubble = mBubbleData.getBubbles().get(i);
+ bubble.inflate(callback,
+ mContext,
+ this,
+ mStackView,
+ mLayerView,
+ mBubbleIconFactory,
+ false /* skipInflation */);
+ }
+ }
+
/**
* Adds or updates a bubble associated with the provided notification entry.
*
@@ -1746,7 +1798,7 @@ public class BubbleController implements ConfigurationChangeListener,
// Update the cached state for queries from SysUI
mImpl.mCachedState.update(update);
- if (isShowingAsBubbleBar() && mBubbleStateListener != null) {
+ if (isShowingAsBubbleBar()) {
BubbleBarUpdate bubbleBarUpdate = update.toBubbleBarUpdate();
// Some updates aren't relevant to the bubble bar so check first.
if (bubbleBarUpdate.anythingChanged()) {
@@ -1868,10 +1920,17 @@ public class BubbleController implements ConfigurationChangeListener,
}
@VisibleForTesting
+ @Nullable
public BubbleStackView getStackView() {
return mStackView;
}
+ @VisibleForTesting
+ @Nullable
+ public BubbleBarLayerView getLayerView() {
+ return mLayerView;
+ }
+
/**
* Check if notification panel is in an expanded state.
* Makes a call to System UI process and delivers the result via {@code callback} on the
@@ -2010,22 +2069,18 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public void registerBubbleListener(IBubblesListener listener) {
- mMainExecutor.execute(() -> {
- mListener.register(listener);
- });
+ mMainExecutor.execute(() -> mListener.register(listener));
}
@Override
public void unregisterBubbleListener(IBubblesListener listener) {
- mMainExecutor.execute(() -> mListener.unregister());
+ mMainExecutor.execute(mListener::unregister);
}
@Override
public void showBubble(String key, boolean onLauncherHome) {
- mMainExecutor.execute(() -> {
- mBubblePositioner.setShowingInBubbleBar(onLauncherHome);
- mController.expandStackAndSelectBubbleFromLauncher(key);
- });
+ mMainExecutor.execute(
+ () -> mController.expandStackAndSelectBubbleFromLauncher(key, onLauncherHome));
}
@Override
@@ -2037,11 +2092,6 @@ public class BubbleController implements ConfigurationChangeListener,
public void collapseBubbles() {
mMainExecutor.execute(() -> mController.collapseStack());
}
-
- @Override
- public void onTaskbarStateChanged(int newState) {
- // TODO (b/269670598)
- }
}
private class BubblesImpl implements Bubbles {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 9860b076264b..34c4934d597a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -309,6 +309,7 @@ public class BubbleStackView extends FrameLayout
String bubblesOnScreen = BubbleDebugConfig.formatBubblesString(
getBubblesOnScreen(), getExpandedBubble());
+ pw.print(" stack visibility : "); pw.println(getVisibility());
pw.print(" bubbles on screen: "); pw.println(bubblesOnScreen);
pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress);
pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing());
@@ -970,6 +971,8 @@ public class BubbleStackView extends FrameLayout
mBubbleContainer.bringToFront();
mBubbleOverflow = mBubbleData.getOverflow();
+
+ resetOverflowView();
mBubbleContainer.addView(mBubbleOverflow.getIconView(),
mBubbleContainer.getChildCount() /* index */,
new FrameLayout.LayoutParams(mPositioner.getBubbleSize(),
@@ -3414,6 +3417,19 @@ public class BubbleStackView extends FrameLayout
}
/**
+ * Removes the overflow view from the stack. This allows for re-adding it later to a new stack.
+ */
+ void resetOverflowView() {
+ BadgedImageView overflowIcon = mBubbleOverflow.getIconView();
+ if (overflowIcon != null) {
+ PhysicsAnimationLayout parent = (PhysicsAnimationLayout) overflowIcon.getParent();
+ if (parent != null) {
+ parent.removeViewNoAnimation(overflowIcon);
+ }
+ }
+ }
+
+ /**
* Holds some commonly queried information about the stack.
*/
public static class StackViewState {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
index 4d329dd5d446..759246eb285d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java
@@ -60,9 +60,11 @@ public interface Bubbles {
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE,
DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT,
DISMISS_OVERFLOW_MAX_REACHED, DISMISS_SHORTCUT_REMOVED, DISMISS_PACKAGE_REMOVED,
- DISMISS_NO_BUBBLE_UP, DISMISS_RELOAD_FROM_DISK, DISMISS_USER_REMOVED})
+ DISMISS_NO_BUBBLE_UP, DISMISS_RELOAD_FROM_DISK, DISMISS_USER_REMOVED,
+ DISMISS_SWITCH_TO_STACK})
@Target({FIELD, LOCAL_VARIABLE, PARAMETER})
- @interface DismissReason {}
+ @interface DismissReason {
+ }
int DISMISS_USER_GESTURE = 1;
int DISMISS_AGED = 2;
@@ -80,6 +82,7 @@ public interface Bubbles {
int DISMISS_NO_BUBBLE_UP = 14;
int DISMISS_RELOAD_FROM_DISK = 15;
int DISMISS_USER_REMOVED = 16;
+ int DISMISS_SWITCH_TO_STACK = 17;
/** Returns a binder that can be passed to an external process to manipulate Bubbles. */
default IBubbles createExternalInterface() {
@@ -120,8 +123,8 @@ public interface Bubbles {
/**
* This method has different behavior depending on:
- * - if an app bubble exists
- * - if an app bubble is expanded
+ * - if an app bubble exists
+ * - if an app bubble is expanded
*
* If no app bubble exists, this will add and expand a bubble with the provided intent. The
* intent must be explicit (i.e. include a package name or fully qualified component class name)
@@ -135,13 +138,13 @@ public interface Bubbles {
* the bubble or bubble stack.
*
* Some notes:
- * - Only one app bubble is supported at a time, regardless of users. Multi-users support is
- * tracked in b/273533235.
- * - Calling this method with a different intent than the existing app bubble will do nothing
+ * - Only one app bubble is supported at a time, regardless of users. Multi-users support is
+ * tracked in b/273533235.
+ * - Calling this method with a different intent than the existing app bubble will do nothing
*
* @param intent the intent to display in the bubble expanded view.
- * @param user the {@link UserHandle} of the user to start this activity for.
- * @param icon the {@link Icon} to use for the bubble view.
+ * @param user the {@link UserHandle} of the user to start this activity for.
+ * @param icon the {@link Icon} to use for the bubble view.
*/
void showOrHideAppBubble(Intent intent, UserHandle user, @Nullable Icon icon);
@@ -172,13 +175,12 @@ public interface Bubbles {
* {@link Bubble#setSuppressNotification}. For the case of suppressed summaries, we also add
* {@link BubbleData#addSummaryToSuppress}.
*
- * @param entry the notification of the BubbleEntry should be removed.
- * @param children the list of child notification of the BubbleEntry from 1st param entry,
- * this will be null if entry does have no children.
+ * @param entry the notification of the BubbleEntry should be removed.
+ * @param children the list of child notification of the BubbleEntry from 1st param entry,
+ * this will be null if entry does have no children.
* @param removeCallback the remove callback for SystemUI side to remove notification, the int
* number should be list position of children list and use -1 for
* removing the parent notification.
- *
* @return true if we want to intercept the dismissal of the entry, else false.
*/
boolean handleDismissalInterception(BubbleEntry entry, @Nullable List<BubbleEntry> children,
@@ -200,9 +202,9 @@ public interface Bubbles {
/**
* Called when new notification entry updated.
*
- * @param entry the {@link BubbleEntry} by the notification.
+ * @param entry the {@link BubbleEntry} by the notification.
* @param shouldBubbleUp {@code true} if this notification should bubble up.
- * @param fromSystem {@code true} if this update is from NotificationManagerService.
+ * @param fromSystem {@code true} if this update is from NotificationManagerService.
*/
void onEntryUpdated(BubbleEntry entry, boolean shouldBubbleUp, boolean fromSystem);
@@ -218,7 +220,7 @@ public interface Bubbles {
* filtering and sorting. This is used to dismiss or create bubbles based on changes in
* permissions on the notification channel or the global setting.
*
- * @param rankingMap the updated ranking map from NotificationListenerService
+ * @param rankingMap the updated ranking map from NotificationListenerService
* @param entryDataByKey a map of ranking key to bubble entry and whether the entry should
* bubble up
*/
@@ -230,9 +232,9 @@ public interface Bubbles {
* Called when a notification channel is modified, in response to
* {@link NotificationListenerService#onNotificationChannelModified}.
*
- * @param pkg the package the notification channel belongs to.
- * @param user the user the notification channel belongs to.
- * @param channel the channel being modified.
+ * @param pkg the package the notification channel belongs to.
+ * @param user the user the notification channel belongs to.
+ * @param channel the channel being modified.
* @param modificationType the type of modification that occurred to the channel.
*/
void onNotificationChannelModified(
@@ -300,7 +302,7 @@ public interface Bubbles {
* Called when the expansion state of the bubble stack changes.
*
* @param isExpanding whether it's expanding or collapsing
- * @param key the notification key associated with bubble being expanded
+ * @param key the notification key associated with bubble being expanded
*/
void onBubbleExpandChanged(boolean isExpanding, String key);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
index 862e818a998b..20ae8469f431 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/IBubbles.aidl
@@ -35,6 +35,4 @@ interface IBubbles {
oneway void collapseBubbles() = 5;
- oneway void onTaskbarStateChanged(in int newState) = 6;
-
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
index 55052e614458..3eb9a9112047 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java
@@ -327,6 +327,12 @@ public class PhysicsAnimationLayout extends FrameLayout {
addViewInternal(child, index, params, false /* isReorder */);
}
+ /** Removes the child view immediately. */
+ public void removeViewNoAnimation(View view) {
+ super.removeView(view);
+ view.setTag(R.id.physics_animator_tag, null);
+ }
+
@Override
public void removeView(View view) {
if (mController != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt
new file mode 100644
index 000000000000..85aaa8ef585c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/BubbleProperties.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.bubbles.properties
+
+/**
+ * An interface for exposing bubble properties via flags which can be controlled easily in tests.
+ */
+interface BubbleProperties {
+ /**
+ * Whether bubble bar is enabled.
+ *
+ * When this is `true`, depending on additional factors, such as screen size and taskbar state,
+ * bubbles will be displayed in the bubble bar instead of floating.
+ *
+ * When this is `false`, bubbles will be floating.
+ */
+ val isBubbleBarEnabled: Boolean
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt
new file mode 100644
index 000000000000..9d8b9a6f3260
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/properties/ProdBubbleProperties.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.bubbles.properties
+
+import android.os.SystemProperties
+
+/** Provides bubble properties in production. */
+object ProdBubbleProperties : BubbleProperties {
+
+ // TODO(b/256873975) Should use proper flag when available to shell/launcher
+ override val isBubbleBarEnabled =
+ SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false)
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 99959aeb0e8c..03f92aaf9ce9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -36,6 +36,7 @@ import com.android.wm.shell.bubbles.BubbleData;
import com.android.wm.shell.bubbles.BubbleDataRepository;
import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubblePositioner;
+import com.android.wm.shell.bubbles.properties.ProdBubbleProperties;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -187,7 +188,7 @@ public abstract class WMShellModule {
statusBarService, windowManager, windowManagerShellWrapper, userManager,
launcherApps, logger, taskStackListener, organizer, positioner, displayController,
oneHandedOptional, dragAndDropController, mainExecutor, mainHandler, bgExecutor,
- taskViewTransitions, syncQueue, wmService);
+ taskViewTransitions, syncQueue, wmService, ProdBubbleProperties.INSTANCE);
}
//
@@ -219,12 +220,12 @@ public abstract class WMShellModule {
desktopTasksController);
}
return new CaptionWindowDecorViewModel(
- context,
- mainHandler,
- mainChoreographer,
- taskOrganizer,
- displayController,
- syncQueue);
+ context,
+ mainHandler,
+ mainChoreographer,
+ taskOrganizer,
+ displayController,
+ syncQueue);
}
//
@@ -584,13 +585,13 @@ public abstract class WMShellModule {
animators.add(fullscreenAnimator);
return new UnfoldAnimationController(
- shellInit,
- transactionPool,
- progressProvider.get(),
- animators,
- unfoldTransitionHandler,
- mainExecutor
- );
+ shellInit,
+ transactionPool,
+ progressProvider.get(),
+ animators,
+ unfoldTransitionHandler,
+ mainExecutor
+ );
}
@Provides
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 5ca936222785..94689ebe8742 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -137,11 +137,13 @@ import com.android.wm.shell.bubbles.BubbleStackView;
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.bubbles.StackEducationViewKt;
+import com.android.wm.shell.bubbles.properties.BubbleProperties;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TaskStackListenerImpl;
+import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.sysui.ShellCommandHandler;
@@ -299,6 +301,8 @@ public class BubblesTest extends SysuiTestCase {
private UserHandle mUser0;
+ private FakeBubbleProperties mBubbleProperties;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -360,6 +364,7 @@ public class BubblesTest extends SysuiTestCase {
mock(UserTracker.class)
);
when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
+ mBubbleProperties = new FakeBubbleProperties();
mBubbleController = new TestableBubbleController(
mContext,
mShellInit,
@@ -384,7 +389,8 @@ public class BubblesTest extends SysuiTestCase {
mock(Handler.class),
mTaskViewTransitions,
mock(SyncTransactionQueue.class),
- mock(IWindowManager.class));
+ mock(IWindowManager.class),
+ mBubbleProperties);
mBubbleController.setExpandListener(mBubbleExpandListener);
spyOn(mBubbleController);
@@ -475,7 +481,7 @@ public class BubblesTest extends SysuiTestCase {
public void testAddBubble() {
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -483,7 +489,7 @@ public class BubblesTest extends SysuiTestCase {
assertFalse(mBubbleController.hasBubbles());
mBubbleController.updateBubble(mBubbleEntry);
assertTrue(mBubbleController.hasBubbles());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -498,7 +504,7 @@ public class BubblesTest extends SysuiTestCase {
assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
verify(mNotifCallback, times(2)).invalidateNotifications(anyString());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -561,7 +567,7 @@ public class BubblesTest extends SysuiTestCase {
assertNull(mBubbleData.getBubbleInStackWithKey(mRow.getKey()));
assertNull(mBubbleData.getBubbleInStackWithKey(mRow2.getKey()));
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -580,7 +586,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Make sure the notif is suppressed
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
@@ -589,7 +595,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.collapseStack();
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
assertStackCollapsed();
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -611,7 +617,7 @@ public class BubblesTest extends SysuiTestCase {
assertStackExpanded();
verify(mBubbleExpandListener, atLeastOnce()).onBubbleExpandChanged(
true, mRow2.getKey());
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Last added is the one that is expanded
assertEquals(mRow2.getKey(), mBubbleData.getSelectedBubble().getKey());
@@ -636,7 +642,7 @@ public class BubblesTest extends SysuiTestCase {
// Collapse
mBubbleController.collapseStack();
assertStackCollapsed();
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -656,7 +662,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Notif is suppressed after expansion
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
@@ -681,7 +687,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleData.setExpanded(true);
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Notif is suppressed after expansion
assertBubbleNotificationSuppressedFromShade(mBubbleEntry);
@@ -710,7 +716,7 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow2.getKey());
@@ -741,7 +747,7 @@ public class BubblesTest extends SysuiTestCase {
// We should be collapsed
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
assertFalse(mBubbleController.hasBubbles());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -754,7 +760,7 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
assertStackExpanded();
verify(mBubbleExpandListener).onBubbleExpandChanged(true, mRow.getKey());
@@ -769,7 +775,7 @@ public class BubblesTest extends SysuiTestCase {
// We should be collapsed
verify(mBubbleExpandListener).onBubbleExpandChanged(false, mRow.getKey());
assertFalse(mBubbleController.hasBubbles());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@@ -787,7 +793,7 @@ public class BubblesTest extends SysuiTestCase {
verify(mBubbleExpandListener, never()).onBubbleExpandChanged(false /* expanded */,
mRow.getKey());
assertStackCollapsed();
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -803,7 +809,7 @@ public class BubblesTest extends SysuiTestCase {
verify(mBubbleExpandListener).onBubbleExpandChanged(true /* expanded */,
mRow.getKey());
assertStackExpanded();
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -820,7 +826,7 @@ public class BubblesTest extends SysuiTestCase {
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -842,7 +848,7 @@ public class BubblesTest extends SysuiTestCase {
// Dot + flyout is hidden because notif is suppressed
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showDot());
assertFalse(mBubbleData.getBubbleInStackWithKey(mRow.getKey()).showFlyout());
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -1247,11 +1253,11 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertStackExpanded();
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Show the menu
stackView.showManageMenu(true);
- assertSysuiStates(true /* stackExpanded */, true /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, true /* manageMenuExpanded */);
assertTrue(stackView.isManageMenuSettingsVisible());
assertTrue(stackView.isManageMenuDontBubbleVisible());
}
@@ -1265,11 +1271,11 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertStackExpanded();
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Show the menu
stackView.showManageMenu(true);
- assertSysuiStates(true /* stackExpanded */, true /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, true /* manageMenuExpanded */);
assertFalse(stackView.isManageMenuSettingsVisible());
assertFalse(stackView.isManageMenuDontBubbleVisible());
}
@@ -1283,15 +1289,15 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertStackExpanded();
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Show the menu
stackView.showManageMenu(true);
- assertSysuiStates(true /* stackExpanded */, true /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, true /* manageMenuExpanded */);
// Hide the menu
stackView.showManageMenu(false);
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -1303,16 +1309,16 @@ public class BubblesTest extends SysuiTestCase {
BubbleStackView stackView = mBubbleController.getStackView();
mBubbleData.setExpanded(true);
assertStackExpanded();
- assertSysuiStates(true /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, false /* manageMenuExpanded */);
// Show the menu
stackView.showManageMenu(true);
- assertSysuiStates(true /* stackExpanded */, true /* mangeMenuExpanded */);
+ assertSysuiStates(true /* stackExpanded */, true /* manageMenuExpanded */);
// Collapse the stack
mBubbleData.setExpanded(false);
- assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
+ assertSysuiStates(false /* stackExpanded */, false /* manageMenuExpanded */);
}
@Test
@@ -1574,7 +1580,7 @@ public class BubblesTest extends SysuiTestCase {
NotificationListenerService.RankingMap rankingMap =
mock(NotificationListenerService.RankingMap.class);
- when(rankingMap.getOrderedKeys()).thenReturn(new String[] { mBubbleEntry.getKey() });
+ when(rankingMap.getOrderedKeys()).thenReturn(new String[]{mBubbleEntry.getKey()});
mBubbleController.onRankingUpdated(rankingMap, entryDataByKey);
// Should no longer be in the stack
@@ -1882,7 +1888,108 @@ public class BubblesTest extends SysuiTestCase {
);
}
- /** Creates a bubble using the userId and package. */
+ @Test
+ public void registerBubbleBarListener_barDisabled_largeScreen_shouldBeIgnored() {
+ mBubbleProperties.mIsBubbleBarEnabled = false;
+ mPositioner.setIsLargeScreen(true);
+ mEntryListener.onEntryAdded(mRow);
+ mBubbleController.updateBubble(mBubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ assertStackMode();
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+
+ assertStackMode();
+
+ assertThat(mBubbleController.getStackView().getBubbleCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void registerBubbleBarListener_barEnabled_smallScreen_shouldBeIgnored() {
+ mBubbleProperties.mIsBubbleBarEnabled = true;
+ mPositioner.setIsLargeScreen(false);
+ mEntryListener.onEntryAdded(mRow);
+ mBubbleController.updateBubble(mBubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ assertStackMode();
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+
+ assertStackMode();
+
+ assertThat(mBubbleController.getStackView().getBubbleCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void registerBubbleBarListener_switchToBarAndBackToStack() {
+ mBubbleProperties.mIsBubbleBarEnabled = true;
+ mPositioner.setIsLargeScreen(true);
+ mEntryListener.onEntryAdded(mRow);
+ mBubbleController.updateBubble(mBubbleEntry);
+ assertTrue(mBubbleController.hasBubbles());
+
+ assertStackMode();
+
+ assertThat(mBubbleData.getBubbles()).hasSize(1);
+ assertBubbleIsInflatedForStack(mBubbleData.getBubbles().get(0));
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+
+ assertBarMode();
+
+ assertThat(mBubbleData.getBubbles()).hasSize(1);
+ assertBubbleIsInflatedForBar(mBubbleData.getBubbles().get(0));
+
+ mBubbleController.unregisterBubbleStateListener();
+
+ assertStackMode();
+
+ assertThat(mBubbleData.getBubbles()).hasSize(1);
+ assertBubbleIsInflatedForStack(mBubbleData.getBubbles().get(0));
+ }
+
+ @Test
+ public void switchBetweenBarAndStack_noBubbles_shouldBeIgnored() {
+ mBubbleProperties.mIsBubbleBarEnabled = false;
+ mPositioner.setIsLargeScreen(true);
+ assertFalse(mBubbleController.hasBubbles());
+
+ assertNoBubbleContainerViews();
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+
+ assertNoBubbleContainerViews();
+
+ mBubbleController.unregisterBubbleStateListener();
+
+ assertNoBubbleContainerViews();
+ }
+
+ @Test
+ public void bubbleBarBubbleExpandedAndCollapsed() {
+ mBubbleProperties.mIsBubbleBarEnabled = true;
+ mPositioner.setIsLargeScreen(true);
+ mEntryListener.onEntryAdded(mRow);
+ mBubbleController.updateBubble(mBubbleEntry);
+
+ FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
+ mBubbleController.registerBubbleStateListener(bubbleStateListener);
+ mBubbleController.expandStackAndSelectBubbleFromLauncher(mBubbleEntry.getKey(), true);
+
+ assertThat(mBubbleController.getLayerView().isExpanded()).isTrue();
+
+ mBubbleController.collapseStack();
+
+ assertThat(mBubbleController.getLayerView().isExpanded()).isFalse();
+ }
+
+ /** Creates a bubble using the userId and package. */
private Bubble createBubble(int userId, String pkg) {
final UserHandle userHandle = new UserHandle(userId);
NotificationEntry workEntry = new NotificationEntryBuilder()
@@ -1998,6 +2105,38 @@ public class BubblesTest extends SysuiTestCase {
assertFalse(mBubbleController.getImplCachedState().isStackExpanded());
}
+ /** Asserts that both the bubble stack and bar views don't exist. */
+ private void assertNoBubbleContainerViews() {
+ assertThat(mBubbleController.getStackView()).isNull();
+ assertThat(mBubbleController.getLayerView()).isNull();
+ }
+
+ /** Asserts that the stack is created and the bar is null. */
+ private void assertStackMode() {
+ assertThat(mBubbleController.getStackView()).isNotNull();
+ assertThat(mBubbleController.getLayerView()).isNull();
+ }
+
+ /** Asserts that the given bubble has the stack expanded view inflated. */
+ private void assertBubbleIsInflatedForStack(Bubble b) {
+ assertThat(b.getIconView()).isNotNull();
+ assertThat(b.getExpandedView()).isNotNull();
+ assertThat(b.getBubbleBarExpandedView()).isNull();
+ }
+
+ /** Asserts that the bar is created and the stack is null. */
+ private void assertBarMode() {
+ assertThat(mBubbleController.getStackView()).isNull();
+ assertThat(mBubbleController.getLayerView()).isNotNull();
+ }
+
+ /** Asserts that the given bubble has the bar expanded view inflated. */
+ private void assertBubbleIsInflatedForBar(Bubble b) {
+ assertThat(b.getIconView()).isNull();
+ assertThat(b.getExpandedView()).isNull();
+ assertThat(b.getBubbleBarExpandedView()).isNotNull();
+ }
+
/**
* Asserts that a bubble notification is suppressed from the shade and also validates the cached
* state is updated.
@@ -2027,4 +2166,19 @@ public class BubblesTest extends SysuiTestCase {
assertThat(mSysUiStateBubblesExpanded).isEqualTo(stackExpanded);
assertThat(mSysUiStateBubblesManageMenuExpanded).isEqualTo(manageMenuExpanded);
}
+
+ private static class FakeBubbleStateListener implements Bubbles.BubbleStateListener {
+ @Override
+ public void onBubbleStateChange(BubbleBarUpdate update) {
+ }
+ }
+
+ private static class FakeBubbleProperties implements BubbleProperties {
+ boolean mIsBubbleBarEnabled = false;
+
+ @Override
+ public boolean isBubbleBarEnabled() {
+ return mIsBubbleBarEnabled;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index 14c3f3c4ada5..5855347c203b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -31,6 +31,7 @@ import com.android.wm.shell.bubbles.BubbleData;
import com.android.wm.shell.bubbles.BubbleDataRepository;
import com.android.wm.shell.bubbles.BubbleLogger;
import com.android.wm.shell.bubbles.BubblePositioner;
+import com.android.wm.shell.bubbles.properties.BubbleProperties;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
@@ -74,13 +75,14 @@ public class TestableBubbleController extends BubbleController {
Handler shellMainHandler,
TaskViewTransitions taskViewTransitions,
SyncTransactionQueue syncQueue,
- IWindowManager wmService) {
+ IWindowManager wmService,
+ BubbleProperties bubbleProperties) {
super(context, shellInit, shellCommandHandler, shellController, data, Runnable::run,
floatingContentCoordinator, dataRepository, statusBarService, windowManager,
windowManagerShellWrapper, userManager, launcherApps, bubbleLogger,
taskStackListener, shellTaskOrganizer, positioner, displayController,
oneHandedOptional, dragAndDropController, shellMainExecutor, shellMainHandler,
- new SyncExecutor(), taskViewTransitions, syncQueue, wmService);
+ new SyncExecutor(), taskViewTransitions, syncQueue, wmService, bubbleProperties);
setInflateSynchronously(true);
onInit();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
index 6edc373d2926..047dc65c4a6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubblePositioner.java
@@ -27,6 +27,7 @@ import com.android.wm.shell.bubbles.BubblePositioner;
public class TestableBubblePositioner extends BubblePositioner {
private int mMaxBubbles;
+ private boolean mIsLargeScreen = false;
public TestableBubblePositioner(Context context,
WindowManager windowManager) {
@@ -46,4 +47,13 @@ public class TestableBubblePositioner extends BubblePositioner {
public int getMaxBubbles() {
return mMaxBubbles;
}
+
+ public void setIsLargeScreen(boolean isLargeScreen) {
+ mIsLargeScreen = isLargeScreen;
+ }
+
+ @Override
+ public boolean isLargeScreen() {
+ return mIsLargeScreen;
+ }
}