diff options
author | 2024-01-30 18:59:23 +0000 | |
---|---|---|
committer | 2024-01-30 18:59:23 +0000 | |
commit | 7593029ac6c19a77b6ce54fcf9dfcb9ad5a9a25c (patch) | |
tree | 1bdd3e40dc633b0f56f79726bd293c4f9893a15f | |
parent | 4ee4e6bcf3754b3867211a8a1221cf4cc7699f94 (diff) | |
parent | e388974d4ab55015ebb8ea37f92a9c3684bfac88 (diff) |
Merge "Decouple BubbleController from some bubble classes" into main
5 files changed, 177 insertions, 56 deletions
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 945b8ac59b98..5f392a8119d7 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 @@ -173,7 +173,7 @@ public class BubbleController implements ConfigurationChangeListener, private final Context mContext; private final BubblesImpl mImpl = new BubblesImpl(); private Bubbles.BubbleExpandListener mExpandListener; - @Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; + @Nullable private final BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer; private final FloatingContentCoordinator mFloatingContentCoordinator; private final BubbleDataRepository mDataRepository; private final WindowManagerShellWrapper mWindowManagerShellWrapper; @@ -197,12 +197,12 @@ public class BubbleController implements ConfigurationChangeListener, private final Handler mMainHandler; private final ShellExecutor mBackgroundExecutor; - private BubbleLogger mLogger; - private BubbleData mBubbleData; + private final BubbleLogger mLogger; + private final BubbleData mBubbleData; @Nullable private BubbleStackView mStackView; @Nullable private BubbleBarLayerView mLayerView; private BubbleIconFactory mBubbleIconFactory; - private BubblePositioner mBubblePositioner; + private final BubblePositioner mBubblePositioner; private Bubbles.SysuiProxy mSysuiProxy; // Tracks the id of the current (foreground) user. @@ -232,13 +232,17 @@ public class BubbleController implements ConfigurationChangeListener, /** Whether or not the BubbleStackView has been added to the WindowManager. */ private boolean mAddedToWindowManager = false; - /** Saved screen density, used to detect display size changes in {@link #onConfigChanged}. */ + /** + * Saved screen density, used to detect display size changes in {@link #onConfigurationChanged}. + */ private int mDensityDpi = Configuration.DENSITY_DPI_UNDEFINED; - /** Saved screen bounds, used to detect screen size changes in {@link #onConfigChanged}. **/ - private Rect mScreenBounds = new Rect(); + /** + * Saved screen bounds, used to detect screen size changes in {@link #onConfigurationChanged}. + */ + private final Rect mScreenBounds = new Rect(); - /** Saved font scale, used to detect font size changes in {@link #onConfigChanged}. */ + /** Saved font scale, used to detect font size changes in {@link #onConfigurationChanged}. */ private float mFontScale = 0; /** Saved direction, used to detect layout direction changes @link #onConfigChanged}. */ @@ -253,9 +257,9 @@ public class BubbleController implements ConfigurationChangeListener, private boolean mIsStatusBarShade = true; /** One handed mode controller to register transition listener. */ - private Optional<OneHandedController> mOneHandedOptional; + private final Optional<OneHandedController> mOneHandedOptional; /** Drag and drop controller to register listener for onDragStarted. */ - private Optional<DragAndDropController> mDragAndDropController; + private final Optional<DragAndDropController> mDragAndDropController; /** Used to send bubble events to launcher. */ private Bubbles.BubbleStateListener mBubbleStateListener; @@ -731,9 +735,11 @@ public class BubbleController implements ConfigurationChangeListener, } } else { if (mStackView == null) { + BubbleStackViewManager bubbleStackViewManager = + BubbleStackViewManager.fromBubbleController(this); mStackView = new BubbleStackView( - mContext, this, mBubbleData, mSurfaceSynchronizer, - mFloatingContentCoordinator, this, mMainExecutor); + mContext, bubbleStackViewManager, mBubblePositioner, mBubbleData, + mSurfaceSynchronizer, mFloatingContentCoordinator, this, mMainExecutor); mStackView.onOrientationChanged(); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); @@ -893,7 +899,6 @@ public class BubbleController implements ConfigurationChangeListener, * Called by the BubbleStackView and whenever all bubbles have animated out, and none have been * added in the meantime. */ - @VisibleForTesting public void onAllBubblesAnimatedOut() { if (mStackView != null) { mStackView.setVisibility(INVISIBLE); @@ -1047,7 +1052,6 @@ public class BubbleController implements ConfigurationChangeListener, return mBubbleData.hasBubbles() || mBubbleData.isShowingOverflow(); } - @VisibleForTesting public boolean isStackExpanded() { return mBubbleData.isExpanded(); } 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 a619401301aa..9facef36a74e 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 @@ -204,7 +204,7 @@ public class BubbleStackView extends FrameLayout Choreographer.getInstance().postFrameCallback(frameCallback); } }; - private final BubbleController mBubbleController; + private final BubbleStackViewManager mManager; private final BubbleData mBubbleData; private final Bubbles.SysuiProxy.Provider mSysuiProxyProvider; private StackViewState mStackViewState = new StackViewState(); @@ -858,6 +858,7 @@ public class BubbleStackView extends FrameLayout private BubbleOverflow mBubbleOverflow; private StackEducationView mStackEduView; + private StackEducationView.Manager mStackEducationViewManager; private ManageEducationView mManageEduView; private DismissView mDismissView; @@ -873,15 +874,16 @@ public class BubbleStackView extends FrameLayout private BubblePositioner mPositioner; @SuppressLint("ClickableViewAccessibility") - public BubbleStackView(Context context, BubbleController bubbleController, - BubbleData data, @Nullable SurfaceSynchronizer synchronizer, + public BubbleStackView(Context context, BubbleStackViewManager bubbleStackViewManager, + BubblePositioner bubblePositioner, BubbleData data, + @Nullable SurfaceSynchronizer synchronizer, FloatingContentCoordinator floatingContentCoordinator, Bubbles.SysuiProxy.Provider sysuiProxyProvider, ShellExecutor mainExecutor) { super(context); mMainExecutor = mainExecutor; - mBubbleController = bubbleController; + mManager = bubbleStackViewManager; mBubbleData = data; mSysuiProxyProvider = sysuiProxyProvider; @@ -893,7 +895,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding); int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation); - mPositioner = mBubbleController.getPositioner(); + mPositioner = bubblePositioner; final TypedArray ta = mContext.obtainStyledAttributes( new int[]{android.R.attr.dialogCornerRadius}); @@ -903,7 +905,7 @@ public class BubbleStackView extends FrameLayout final Runnable onBubbleAnimatedOut = () -> { if (getBubbleCount() == 0) { mExpandedViewTemporarilyHidden = false; - mBubbleController.onAllBubblesAnimatedOut(); + mManager.onAllBubblesAnimatedOut(); } }; mStackAnimationController = new StackAnimationController( @@ -1383,7 +1385,9 @@ public class BubbleStackView extends FrameLayout return false; } if (mStackEduView == null) { - mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController); + mStackEducationViewManager = mManager::updateWindowFlagsForBackpress; + mStackEduView = + new StackEducationView(mContext, mPositioner, mStackEducationViewManager); addView(mStackEduView); } return showStackEdu(); @@ -1412,7 +1416,9 @@ public class BubbleStackView extends FrameLayout private void updateUserEdu() { if (isStackEduVisible() && !mStackEduView.isHiding()) { removeView(mStackEduView); - mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController); + mStackEducationViewManager = mManager::updateWindowFlagsForBackpress; + mStackEduView = + new StackEducationView(mContext, mPositioner, mStackEducationViewManager); addView(mStackEduView); showStackEdu(); } @@ -2106,7 +2112,7 @@ public class BubbleStackView extends FrameLayout logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED); - mBubbleController.isNotificationPanelExpanded(notifPanelExpanded -> { + mManager.checkNotificationPanelExpandedState(notifPanelExpanded -> { if (!notifPanelExpanded && mIsExpanded) { startMonitoringSwipeUpGesture(); } @@ -2227,7 +2233,7 @@ public class BubbleStackView extends FrameLayout */ void hideCurrentInputMethod() { mPositioner.setImeVisible(false, 0); - mBubbleController.hideCurrentInputMethod(); + mManager.hideCurrentInputMethod(); } /** Set the stack position to whatever the positioner says. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackViewManager.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackViewManager.kt new file mode 100644 index 000000000000..fb597a05663b --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackViewManager.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 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 + +import java.util.function.Consumer + +/** Defines callbacks from [BubbleStackView] to its manager. */ +interface BubbleStackViewManager { + + /** Notifies that all bubbles animated out. */ + fun onAllBubblesAnimatedOut() + + /** Notifies whether backpress should be intercepted. */ + fun updateWindowFlagsForBackpress(interceptBack: Boolean) + + /** + * Checks the current expansion state of the notification panel, and invokes [callback] with the + * result. + */ + fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) + + /** Requests to hide the current input method. */ + fun hideCurrentInputMethod() + + companion object { + + @JvmStatic + fun fromBubbleController(controller: BubbleController) = object : BubbleStackViewManager { + override fun onAllBubblesAnimatedOut() { + controller.onAllBubblesAnimatedOut() + } + + override fun updateWindowFlagsForBackpress(interceptBack: Boolean) { + controller.updateWindowFlagsForBackpress(interceptBack) + } + + override fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) { + controller.isNotificationPanelExpanded(callback) + } + + override fun hideCurrentInputMethod() { + controller.hideCurrentInputMethod() + } + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt index 95f101722e89..c4108c4129e9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt @@ -35,7 +35,7 @@ import com.android.wm.shell.animation.Interpolators class StackEducationView( context: Context, private val positioner: BubblePositioner, - private val controller: BubbleController + private val manager: Manager ) : LinearLayout(context) { companion object { @@ -44,6 +44,12 @@ class StackEducationView( private const val ANIMATE_DURATION_SHORT: Long = 40 } + /** Callbacks to notify managers of [StackEducationView] about events. */ + interface Manager { + /** Notifies whether backpress should be intercepted. */ + fun updateWindowFlagsForBackpress(interceptBack: Boolean) + } + private val view by lazy { requireViewById<View>(R.id.stack_education_layout) } private val titleTextView by lazy { requireViewById<TextView>(R.id.stack_education_title) } private val descTextView by lazy { requireViewById<TextView>(R.id.stack_education_description) } @@ -93,7 +99,7 @@ class StackEducationView( override fun onDetachedFromWindow() { super.onDetachedFromWindow() setOnKeyListener(null) - controller.updateWindowFlagsForBackpress(false /* interceptBack */) + manager.updateWindowFlagsForBackpress(false /* interceptBack */) } private fun setTextColor() { @@ -124,7 +130,7 @@ class StackEducationView( isHiding = false if (visibility == VISIBLE) return false - controller.updateWindowFlagsForBackpress(true /* interceptBack */) + manager.updateWindowFlagsForBackpress(true /* interceptBack */) layoutParams.width = if (positioner.isLargeScreen || positioner.isLandscape) context.resources.getDimensionPixelSize(R.dimen.bubbles_user_education_width) @@ -185,7 +191,7 @@ class StackEducationView( if (visibility != VISIBLE || isHiding) return isHiding = true - controller.updateWindowFlagsForBackpress(false /* interceptBack */) + manager.updateWindowFlagsForBackpress(false /* interceptBack */) animate() .alpha(0f) .setDuration(if (isExpanding) ANIMATE_DURATION_SHORT else ANIMATE_DURATION) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt index 4878df806f82..75965d6d68d9 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt @@ -56,9 +56,7 @@ import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever -/** - * Tests for loading / inflating views & icons for a bubble. - */ +/** Tests for loading / inflating views & icons for a bubble. */ @SmallTest @RunWith(AndroidTestingRunner::class) @RunWithLooper(setAsMainLooper = true) @@ -76,25 +74,33 @@ class BubbleViewInfoTest : ShellTestCase() { @Before fun setup() { metadataFlagListener = Bubbles.BubbleMetadataFlagListener {} - iconFactory = BubbleIconFactory(context, + iconFactory = + BubbleIconFactory( + context, 60, 30, Color.RED, - mContext.resources.getDimensionPixelSize( - R.dimen.importance_ring_stroke_width)) + mContext.resources.getDimensionPixelSize(R.dimen.importance_ring_stroke_width) + ) mainExecutor = TestShellExecutor() val windowManager = context.getSystemService(WindowManager::class.java) val shellInit = ShellInit(mainExecutor) val shellCommandHandler = ShellCommandHandler() - val shellController = ShellController(context, shellInit, shellCommandHandler, - mainExecutor) + val shellController = ShellController(context, shellInit, shellCommandHandler, mainExecutor) val bubblePositioner = BubblePositioner(context, windowManager) - val bubbleData = BubbleData(context, mock<BubbleLogger>(), bubblePositioner, - BubbleEducationController(context), mainExecutor) + val bubbleData = + BubbleData( + context, + mock<BubbleLogger>(), + bubblePositioner, + BubbleEducationController(context), + mainExecutor + ) val surfaceSynchronizer = { obj: Runnable -> obj.run() } - bubbleController = BubbleController( + bubbleController = + BubbleController( context, shellInit, shellCommandHandler, @@ -122,18 +128,36 @@ class BubbleViewInfoTest : ShellTestCase() { mock<Transitions>(), mock<SyncTransactionQueue>(), mock<IWindowManager>(), - mock<BubbleProperties>()) + mock<BubbleProperties>() + ) - bubbleStackView = BubbleStackView(context, bubbleController, bubbleData, - surfaceSynchronizer, FloatingContentCoordinator(), bubbleController, mainExecutor) + val bubbleStackViewManager = BubbleStackViewManager.fromBubbleController(bubbleController) + bubbleStackView = + BubbleStackView( + context, + bubbleStackViewManager, + bubblePositioner, + bubbleData, + surfaceSynchronizer, + FloatingContentCoordinator(), + bubbleController, + mainExecutor + ) bubbleBarLayerView = BubbleBarLayerView(context, bubbleController) } @Test fun testPopulate() { bubble = createBubbleWithShortcut() - val info = BubbleViewInfoTask.BubbleViewInfo.populate(context, - bubbleController, bubbleStackView, iconFactory, bubble, false /* skipInflation */) + val info = + BubbleViewInfoTask.BubbleViewInfo.populate( + context, + bubbleController, + bubbleStackView, + iconFactory, + bubble, + false /* skipInflation */ + ) assertThat(info!!).isNotNull() assertThat(info.imageView).isNotNull() @@ -151,9 +175,15 @@ class BubbleViewInfoTest : ShellTestCase() { @Test fun testPopulateForBubbleBar() { bubble = createBubbleWithShortcut() - val info = BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar(context, - bubbleController, bubbleBarLayerView, iconFactory, bubble, - false /* skipInflation */) + val info = + BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar( + context, + bubbleController, + bubbleBarLayerView, + iconFactory, + bubble, + false /* skipInflation */ + ) assertThat(info!!).isNotNull() assertThat(info.imageView).isNull() @@ -176,12 +206,18 @@ class BubbleViewInfoTest : ShellTestCase() { // exception here if the app has an issue loading the shortcut icon; we default to // the app icon in that case / none of the icons will be null. val mockIconFactory = mock<BubbleIconFactory>() - whenever(mockIconFactory.getBubbleDrawable(eq(context), eq(bubble.shortcutInfo), - any())).doThrow(RuntimeException()) + whenever(mockIconFactory.getBubbleDrawable(eq(context), eq(bubble.shortcutInfo), any())) + .doThrow(RuntimeException()) - val info = BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar(context, - bubbleController, bubbleBarLayerView, iconFactory, bubble, - true /* skipInflation */) + val info = + BubbleViewInfoTask.BubbleViewInfo.populateForBubbleBar( + context, + bubbleController, + bubbleBarLayerView, + iconFactory, + bubble, + true /* skipInflation */ + ) assertThat(info).isNotNull() assertThat(info?.shortcutInfo).isNotNull() @@ -194,8 +230,17 @@ class BubbleViewInfoTest : ShellTestCase() { private fun createBubbleWithShortcut(): Bubble { val shortcutInfo = ShortcutInfo.Builder(mContext, "mockShortcutId").build() - return Bubble("mockKey", shortcutInfo, 1000, Resources.ID_NULL, - "mockTitle", 0 /* taskId */, "mockLocus", true /* isDismissible */, - mainExecutor, metadataFlagListener) + return Bubble( + "mockKey", + shortcutInfo, + 1000, + Resources.ID_NULL, + "mockTitle", + 0 /* taskId */, + "mockLocus", + true /* isDismissible */, + mainExecutor, + metadataFlagListener + ) } -}
\ No newline at end of file +} |