Loading libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/fold/BubblesUnfoldListenerTest.kt +23 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ class BubblesUnfoldListenerTest { private var isStayAwakeOnFold = false private var barToFloatingTransitionStarted = false private var barToFullscreenTransitionStarted = false @Before fun setUp() { Loading @@ -76,10 +77,15 @@ class BubblesUnfoldListenerTest { backgroundExecutor ) foldLockSettingsObserver = BubblesFoldLockSettingsObserver { isStayAwakeOnFold } unfoldListener = BubblesUnfoldListener(bubbleData, foldLockSettingsObserver) { unfoldListener = BubblesUnfoldListener( bubbleData, foldLockSettingsObserver) { bubble, moveToFullscreen -> if (moveToFullscreen) { barToFullscreenTransitionStarted = true } else { barToFloatingTransitionStarted = true } } } @Test fun fold_noBubbles_shouldNotStartTransition() { Loading Loading @@ -149,4 +155,19 @@ class BubblesUnfoldListenerTest { unfoldListener.onFoldStateChanged(isFolded = false) assertThat(barToFloatingTransitionStarted).isFalse() } @Test fun fold_expandedFixedLandscapeBubble_staysAwakeOnFold_shouldStartFullscreenTransition() { isStayAwakeOnFold = true val bubble = FakeBubbleFactory.createChatBubble(context) bubble.setIsTopActivityFixedOrientationLandscape(true) bubbleData.notificationEntryUpdated(bubble, true, false) assertThat(bubbleData.hasBubbles()).isTrue() bubbleData.setSelectedBubbleAndExpandStack(bubble) assertThat(bubbleData.isExpanded).isTrue() unfoldListener.onFoldStateChanged(isFolded = true) assertThat(barToFloatingTransitionStarted).isFalse() assertThat(barToFullscreenTransitionStarted).isTrue() } } libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +12 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,7 @@ public class Bubble implements BubbleViewProvider { @Nullable private Icon mIcon; private boolean mIsBubble; private boolean mIsTopActivityFixedOrientationLandscape; private boolean mIsTextChanged; private boolean mIsDismissable; private boolean mShouldSuppressNotificationDot; Loading Loading @@ -1046,6 +1047,13 @@ public class Bubble implements BubbleViewProvider { } } /** * Sets whether the task's top activity is fixed orientation landscape. */ public void setIsTopActivityFixedOrientationLandscape(boolean isLandscape) { mIsTopActivityFixedOrientationLandscape = isLandscape; } /** * Whether the bubble for this notification should show a dot indicating updated content. */ Loading Loading @@ -1277,6 +1285,10 @@ public class Bubble implements BubbleViewProvider { return mFlags; } public boolean isTopActivityFixedOrientationLandscape() { return mIsTopActivityFixedOrientationLandscape; } @Override public String toString() { return "Bubble{" + mKey + '}'; Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +21 −5 Original line number Diff line number Diff line Loading @@ -334,6 +334,9 @@ public class BubbleController implements ConfigurationChangeListener, /** Used to block task view transitions while we're switching over to floating views. */ private IBinder mBarToFloatingTransition = null; /** Used to indicate that bubbles should not be added back on move to fullscreen. */ private boolean mSkipAddingBackBubbleOnMoveToFullScreen = false; public BubbleController(Context context, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading Loading @@ -435,11 +438,17 @@ public class BubbleController implements ConfigurationChangeListener, private void addUnfoldProgressProviderListener( ShellUnfoldProgressProvider unfoldProgressProvider) { BubblesUnfoldListener unfoldListener = new BubblesUnfoldListener(mBubbleData, mFoldLockSettingsObserver, bubble -> { BubblesUnfoldListener unfoldListener = new BubblesUnfoldListener( mBubbleData, mFoldLockSettingsObserver, (bubble, moveToFullscreen) -> { if (moveToFullscreen) { bubble.getTaskView().moveToFullscreen(); mSkipAddingBackBubbleOnMoveToFullScreen = true; } else { mBarToFloatingTransition = new Binder(); mBubbleTransitions.mTaskViewTransitions.enqueueExternal( bubble.getTaskView().getController(), () -> mBarToFloatingTransition); bubble.getTaskView().getController(), () -> mBarToFloatingTransition); } return Unit.INSTANCE; }); unfoldProgressProvider.addListener(mMainExecutor, unfoldListener); Loading Loading @@ -2093,6 +2102,13 @@ public class BubbleController implements ConfigurationChangeListener, } for (int i = mBubbleData.getBubbles().size() - 1; i >= 0; i--) { Bubble bubble = mBubbleData.getBubbles().get(i); if (bubble.getKey().equals(mBubbleData.getSelectedBubbleKey()) && mSkipAddingBackBubbleOnMoveToFullScreen) { // Reset and skip inflating the floating view for the selected bubble, which will // also skip adding it to the stack view in the callback. mSkipAddingBackBubbleOnMoveToFullScreen = false; continue; } bubble.inflate(callback, mContext, mExpandedViewManager, Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +12 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles.bar; import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static com.android.wm.shell.bubbles.util.BubbleUtils.isValidToBubble; Loading Loading @@ -414,10 +415,19 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { if (!isValidToBubble(taskInfo)) { // TODO(b/411558731): Besides just showing a warning toast, also force the app to return // to fullscreen, similar to split screen behavior when not supported. Toast.makeText(mContext, R.string.bubble_not_supported_text, Toast.LENGTH_SHORT).show(); } if (mBubble != null && taskInfo != null && taskInfo.topActivityInfo != null) { // TODO(b/419379112): Whether a Foldable device is large screen or a small screen // (unfolded or folded) is only updated in onTaskInfoChanged AFTER // onFoldStateChanged is called, so the top Activity being fixed orientation // landscape is used as a proxy when unfolded in onFoldStateChanged to decide how // the Bubble should be displayed. It'd be better just have move that logic here and // use isValidToBubble instead. final boolean isLandscape = isFixedOrientationLandscape(taskInfo.topActivityInfo.screenOrientation); mBubble.setIsTopActivityFixedOrientationLandscape(isLandscape); } } @Override Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/fold/BubblesUnfoldListener.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import com.android.wm.shell.unfold.ShellUnfoldProgressProvider class BubblesUnfoldListener( private val bubbleData: BubbleData, private val foldLockSettingsObserver: BubblesFoldLockSettingsObserver, private val onStartBarToFloatingTransition: (Bubble) -> Unit private val onStartBarToFloatingOrFullscreenTransition: (Bubble, Boolean) -> Unit ) : ShellUnfoldProgressProvider.UnfoldListener { override fun onFoldStateChanged(isFolded: Boolean) { Loading @@ -39,7 +39,8 @@ class BubblesUnfoldListener( && selectedBubble is Bubble && foldLockSettingsObserver.isStayAwakeOnFold() ) { onStartBarToFloatingTransition(selectedBubble) val moveToFullscreen: Boolean = selectedBubble.isTopActivityFixedOrientationLandscape onStartBarToFloatingOrFullscreenTransition(selectedBubble, moveToFullscreen) } } } Loading
libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/fold/BubblesUnfoldListenerTest.kt +23 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ class BubblesUnfoldListenerTest { private var isStayAwakeOnFold = false private var barToFloatingTransitionStarted = false private var barToFullscreenTransitionStarted = false @Before fun setUp() { Loading @@ -76,10 +77,15 @@ class BubblesUnfoldListenerTest { backgroundExecutor ) foldLockSettingsObserver = BubblesFoldLockSettingsObserver { isStayAwakeOnFold } unfoldListener = BubblesUnfoldListener(bubbleData, foldLockSettingsObserver) { unfoldListener = BubblesUnfoldListener( bubbleData, foldLockSettingsObserver) { bubble, moveToFullscreen -> if (moveToFullscreen) { barToFullscreenTransitionStarted = true } else { barToFloatingTransitionStarted = true } } } @Test fun fold_noBubbles_shouldNotStartTransition() { Loading Loading @@ -149,4 +155,19 @@ class BubblesUnfoldListenerTest { unfoldListener.onFoldStateChanged(isFolded = false) assertThat(barToFloatingTransitionStarted).isFalse() } @Test fun fold_expandedFixedLandscapeBubble_staysAwakeOnFold_shouldStartFullscreenTransition() { isStayAwakeOnFold = true val bubble = FakeBubbleFactory.createChatBubble(context) bubble.setIsTopActivityFixedOrientationLandscape(true) bubbleData.notificationEntryUpdated(bubble, true, false) assertThat(bubbleData.hasBubbles()).isTrue() bubbleData.setSelectedBubbleAndExpandStack(bubble) assertThat(bubbleData.isExpanded).isTrue() unfoldListener.onFoldStateChanged(isFolded = true) assertThat(barToFloatingTransitionStarted).isFalse() assertThat(barToFullscreenTransitionStarted).isTrue() } }
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +12 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,7 @@ public class Bubble implements BubbleViewProvider { @Nullable private Icon mIcon; private boolean mIsBubble; private boolean mIsTopActivityFixedOrientationLandscape; private boolean mIsTextChanged; private boolean mIsDismissable; private boolean mShouldSuppressNotificationDot; Loading Loading @@ -1046,6 +1047,13 @@ public class Bubble implements BubbleViewProvider { } } /** * Sets whether the task's top activity is fixed orientation landscape. */ public void setIsTopActivityFixedOrientationLandscape(boolean isLandscape) { mIsTopActivityFixedOrientationLandscape = isLandscape; } /** * Whether the bubble for this notification should show a dot indicating updated content. */ Loading Loading @@ -1277,6 +1285,10 @@ public class Bubble implements BubbleViewProvider { return mFlags; } public boolean isTopActivityFixedOrientationLandscape() { return mIsTopActivityFixedOrientationLandscape; } @Override public String toString() { return "Bubble{" + mKey + '}'; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +21 −5 Original line number Diff line number Diff line Loading @@ -334,6 +334,9 @@ public class BubbleController implements ConfigurationChangeListener, /** Used to block task view transitions while we're switching over to floating views. */ private IBinder mBarToFloatingTransition = null; /** Used to indicate that bubbles should not be added back on move to fullscreen. */ private boolean mSkipAddingBackBubbleOnMoveToFullScreen = false; public BubbleController(Context context, ShellInit shellInit, ShellCommandHandler shellCommandHandler, Loading Loading @@ -435,11 +438,17 @@ public class BubbleController implements ConfigurationChangeListener, private void addUnfoldProgressProviderListener( ShellUnfoldProgressProvider unfoldProgressProvider) { BubblesUnfoldListener unfoldListener = new BubblesUnfoldListener(mBubbleData, mFoldLockSettingsObserver, bubble -> { BubblesUnfoldListener unfoldListener = new BubblesUnfoldListener( mBubbleData, mFoldLockSettingsObserver, (bubble, moveToFullscreen) -> { if (moveToFullscreen) { bubble.getTaskView().moveToFullscreen(); mSkipAddingBackBubbleOnMoveToFullScreen = true; } else { mBarToFloatingTransition = new Binder(); mBubbleTransitions.mTaskViewTransitions.enqueueExternal( bubble.getTaskView().getController(), () -> mBarToFloatingTransition); bubble.getTaskView().getController(), () -> mBarToFloatingTransition); } return Unit.INSTANCE; }); unfoldProgressProvider.addListener(mMainExecutor, unfoldListener); Loading Loading @@ -2093,6 +2102,13 @@ public class BubbleController implements ConfigurationChangeListener, } for (int i = mBubbleData.getBubbles().size() - 1; i >= 0; i--) { Bubble bubble = mBubbleData.getBubbles().get(i); if (bubble.getKey().equals(mBubbleData.getSelectedBubbleKey()) && mSkipAddingBackBubbleOnMoveToFullScreen) { // Reset and skip inflating the floating view for the selected bubble, which will // also skip adding it to the stack view in the callback. mSkipAddingBackBubbleOnMoveToFullScreen = false; continue; } bubble.inflate(callback, mContext, mExpandedViewManager, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +12 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.bubbles.bar; import static android.content.pm.ActivityInfo.isFixedOrientationLandscape; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static com.android.wm.shell.bubbles.util.BubbleUtils.isValidToBubble; Loading Loading @@ -414,10 +415,19 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView @Override public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { if (!isValidToBubble(taskInfo)) { // TODO(b/411558731): Besides just showing a warning toast, also force the app to return // to fullscreen, similar to split screen behavior when not supported. Toast.makeText(mContext, R.string.bubble_not_supported_text, Toast.LENGTH_SHORT).show(); } if (mBubble != null && taskInfo != null && taskInfo.topActivityInfo != null) { // TODO(b/419379112): Whether a Foldable device is large screen or a small screen // (unfolded or folded) is only updated in onTaskInfoChanged AFTER // onFoldStateChanged is called, so the top Activity being fixed orientation // landscape is used as a proxy when unfolded in onFoldStateChanged to decide how // the Bubble should be displayed. It'd be better just have move that logic here and // use isValidToBubble instead. final boolean isLandscape = isFixedOrientationLandscape(taskInfo.topActivityInfo.screenOrientation); mBubble.setIsTopActivityFixedOrientationLandscape(isLandscape); } } @Override Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/fold/BubblesUnfoldListener.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import com.android.wm.shell.unfold.ShellUnfoldProgressProvider class BubblesUnfoldListener( private val bubbleData: BubbleData, private val foldLockSettingsObserver: BubblesFoldLockSettingsObserver, private val onStartBarToFloatingTransition: (Bubble) -> Unit private val onStartBarToFloatingOrFullscreenTransition: (Bubble, Boolean) -> Unit ) : ShellUnfoldProgressProvider.UnfoldListener { override fun onFoldStateChanged(isFolded: Boolean) { Loading @@ -39,7 +39,8 @@ class BubblesUnfoldListener( && selectedBubble is Bubble && foldLockSettingsObserver.isStayAwakeOnFold() ) { onStartBarToFloatingTransition(selectedBubble) val moveToFullscreen: Boolean = selectedBubble.isTopActivityFixedOrientationLandscape onStartBarToFloatingOrFullscreenTransition(selectedBubble, moveToFullscreen) } } }