From 6e5749c35fc35119302d8ef791115527ace9244c Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Mon, 15 May 2023 21:52:48 +0000 Subject: [PATCH 1/2] Revert "Use ComponentCallbacks instead of ConfigurationChangeListener" This reverts commit 2c4955bcf664e9ed5b9fa5b7fb201c923f9a9b68. Reason for revert: b/281748524#comment14 Change-Id: Id53bfc8ca6177db05c8b55562c170373d23acfa4 --- .../wm/shell/bubbles/BubbleController.java | 124 +++++++----------- .../android/systemui/wmshell/BubblesTest.java | 65 +++------ .../systemui/SysuiTestableContext.java | 5 - 3 files changed, 67 insertions(+), 127 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 698681029595d..3eb9fa2eef6b2 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 @@ -17,18 +17,12 @@ package com.android.wm.shell.bubbles; import static android.app.ActivityTaskManager.INVALID_TASK_ID; -import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS; -import static android.content.pm.ActivityInfo.CONFIG_DENSITY; -import static android.content.pm.ActivityInfo.CONFIG_FONT_SCALE; -import static android.content.pm.ActivityInfo.CONFIG_LAYOUT_DIRECTION; -import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED; import static android.service.notification.NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED; import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_CONTROLLER; import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_GESTURE; @@ -53,7 +47,6 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.PendingIntent; import android.content.BroadcastReceiver; -import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -81,6 +74,7 @@ import android.util.Pair; import android.util.SparseArray; import android.view.IWindowManager; import android.view.SurfaceControl; +import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.WindowInsets; @@ -108,7 +102,6 @@ import com.android.wm.shell.common.SingleInstanceRemoteListener; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; -import com.android.wm.shell.common.annotations.ExternalMainThread; import com.android.wm.shell.common.annotations.ShellBackgroundThread; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.bubbles.BubbleBarUpdate; @@ -116,6 +109,7 @@ import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.PinnedStackListenerForwarder; +import com.android.wm.shell.sysui.ConfigurationChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; @@ -141,7 +135,7 @@ import java.util.function.IntConsumer; * * The controller manages addition, removal, and visible state of bubbles on screen. */ -public class BubbleController implements ComponentCallbacks2, +public class BubbleController implements ConfigurationChangeListener, RemoteCallable { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; @@ -159,6 +153,7 @@ public class BubbleController implements ComponentCallbacks2, private static final boolean BUBBLE_BAR_ENABLED = SystemProperties.getBoolean("persist.wm.debug.bubble_bar", false); + /** * Common interface to send updates to bubble views. */ @@ -242,17 +237,17 @@ public class BubbleController implements ComponentCallbacks2, /** Whether or not the BubbleStackView has been added to the WindowManager. */ private boolean mAddedToWindowManager = false; - /** - * Saved configuration, used to detect changes in - * {@link #onConfigurationChanged(Configuration)} - */ - private final Configuration mLastConfiguration = new Configuration(); + /** Saved screen density, used to detect display size changes in {@link #onConfigChanged}. */ + private int mDensityDpi = Configuration.DENSITY_DPI_UNDEFINED; - /** - * Saved screen bounds, used to detect screen size changes in - * {@link #onConfigurationChanged(Configuration)}. - */ - private final Rect mScreenBounds = new Rect(); + /** Saved screen bounds, used to detect screen size changes in {@link #onConfigChanged}. **/ + private Rect mScreenBounds = new Rect(); + + /** Saved font scale, used to detect font size changes in {@link #onConfigChanged}. */ + private float mFontScale = 0; + + /** Saved direction, used to detect layout direction changes @link #onConfigChanged}. */ + private int mLayoutDirection = View.LAYOUT_DIRECTION_UNDEFINED; /** Saved insets, used to detect WindowInset changes. */ private WindowInsets mWindowInsets; @@ -298,8 +293,7 @@ public class BubbleController implements ComponentCallbacks2, TaskViewTransitions taskViewTransitions, SyncTransactionQueue syncQueue, IWindowManager wmService) { - mContext = context.createWindowContext(TYPE_APPLICATION_OVERLAY, null); - mLastConfiguration.setTo(mContext.getResources().getConfiguration()); + mContext = context; mShellCommandHandler = shellCommandHandler; mShellController = shellController; mLauncherApps = launcherApps; @@ -323,11 +317,11 @@ public class BubbleController implements ComponentCallbacks2, mBubblePositioner = positioner; mBubbleData = data; mSavedUserBubbleData = new SparseArray<>(); - mBubbleIconFactory = new BubbleIconFactory(mContext, - mContext.getResources().getDimensionPixelSize(R.dimen.bubble_size), - mContext.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size), - mContext.getResources().getColor(R.color.important_conversation), - mContext.getResources().getDimensionPixelSize( + mBubbleIconFactory = new BubbleIconFactory(context, + context.getResources().getDimensionPixelSize(R.dimen.bubble_size), + context.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size), + context.getResources().getColor(R.color.important_conversation), + context.getResources().getDimensionPixelSize( com.android.internal.R.dimen.importance_ring_stroke_width)); mDisplayController = displayController; mTaskViewTransitions = taskViewTransitions; @@ -488,6 +482,7 @@ public class BubbleController implements ComponentCallbacks2, } mCurrentProfiles = userProfiles; + mShellController.addConfigurationChangeListener(this); mShellController.addExternalInterface(KEY_EXTRA_SHELL_BUBBLES, this::createExternalInterface, this); mShellCommandHandler.addDumpCallback(this::dump, this); @@ -779,7 +774,6 @@ public class BubbleController implements ComponentCallbacks2, try { mAddedToWindowManager = true; registerBroadcastReceiver(); - mContext.registerComponentCallbacks(this); mBubbleData.getOverflow().initialize(this); // (TODO: b/273314541) some duplication in the inset listener if (isShowingAsBubbleBar()) { @@ -837,7 +831,6 @@ public class BubbleController implements ComponentCallbacks2, // Put on background for this binder call, was causing jank mBackgroundExecutor.execute(() -> { try { - mContext.unregisterComponentCallbacks(this); mContext.unregisterReceiver(mBroadcastReceiver); } catch (IllegalArgumentException e) { // Not sure if this happens in production, but was happening in tests @@ -937,7 +930,8 @@ public class BubbleController implements ComponentCallbacks2, mSavedUserBubbleData.remove(userId); } - private void onThemeChanged() { + @Override + public void onThemeChanged() { if (mStackView != null) { mStackView.onThemeChanged(); } @@ -969,60 +963,34 @@ public class BubbleController implements ComponentCallbacks2, } } - // Note: Component callbacks are always called on the main thread of the process - @ExternalMainThread @Override public void onConfigurationChanged(Configuration newConfig) { - mMainExecutor.execute(() -> { - final int diff = newConfig.diff(mLastConfiguration); - final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0 - || (diff & CONFIG_UI_MODE) != 0; - if (themeChanged) { - onThemeChanged(); + if (mBubblePositioner != null) { + mBubblePositioner.update(); + } + if (mStackView != null && newConfig != null) { + if (newConfig.densityDpi != mDensityDpi + || !newConfig.windowConfiguration.getBounds().equals(mScreenBounds)) { + mDensityDpi = newConfig.densityDpi; + mScreenBounds.set(newConfig.windowConfiguration.getBounds()); + mBubbleData.onMaxBubblesChanged(); + mBubbleIconFactory = new BubbleIconFactory(mContext, + mContext.getResources().getDimensionPixelSize(R.dimen.bubble_size), + mContext.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size), + mContext.getResources().getColor(R.color.important_conversation), + mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.importance_ring_stroke_width)); + mStackView.onDisplaySizeChanged(); } - if (mBubblePositioner != null) { - mBubblePositioner.update(); + if (newConfig.fontScale != mFontScale) { + mFontScale = newConfig.fontScale; + mStackView.updateFontScale(); } - if (mStackView != null) { - final boolean densityChanged = (diff & CONFIG_DENSITY) != 0; - final boolean fontScaleChanged = (diff & CONFIG_FONT_SCALE) != 0; - final boolean layoutDirectionChanged = (diff & CONFIG_LAYOUT_DIRECTION) != 0; - if (densityChanged - || !newConfig.windowConfiguration.getBounds().equals(mScreenBounds)) { - mScreenBounds.set(newConfig.windowConfiguration.getBounds()); - mBubbleData.onMaxBubblesChanged(); - mBubbleIconFactory = new BubbleIconFactory(mContext, - mContext.getResources().getDimensionPixelSize(R.dimen.bubble_size), - mContext.getResources().getDimensionPixelSize( - R.dimen.bubble_badge_size), - mContext.getResources().getColor(R.color.important_conversation), - mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.importance_ring_stroke_width)); - mStackView.onDisplaySizeChanged(); - } - if (fontScaleChanged) { - mStackView.updateFontScale(); - } - if (layoutDirectionChanged) { - mStackView.onLayoutDirectionChanged(newConfig.getLayoutDirection()); - } + if (newConfig.getLayoutDirection() != mLayoutDirection) { + mLayoutDirection = newConfig.getLayoutDirection(); + mStackView.onLayoutDirectionChanged(mLayoutDirection); } - mLastConfiguration.setTo(newConfig); - }); - } - - // Note: Component callbacks are always called on the main thread of the process - @ExternalMainThread - @Override - public void onTrimMemory(int level) { - // Do nothing - } - - // Note: Component callbacks are always called on the main thread of the process - @ExternalMainThread - @Override - public void onLowMemory() { - // Do nothing + } } private void onNotificationPanelExpandedChanged(boolean expanded) { 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 f0683a4628b61..47a86b1fca5cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -300,10 +300,6 @@ public class BubblesTest extends SysuiTestCase { private UserHandle mUser0; - // The window context being used by the controller, use this to verify - // any actions on the context. - private Context mBubbleControllerContext; - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -440,8 +436,6 @@ public class BubblesTest extends SysuiTestCase { // Get a reference to KeyguardStateController.Callback verify(mKeyguardStateController, atLeastOnce()) .addCallback(mKeyguardStateControllerCallbackCaptor.capture()); - - mBubbleControllerContext = mBubbleController.getContext(); } @After @@ -473,6 +467,11 @@ public class BubblesTest extends SysuiTestCase { verify(mShellInit, times(1)).addInitCallback(any(), any()); } + @Test + public void instantiateController_registerConfigChangeListener() { + verify(mShellController, times(1)).addConfigurationChangeListener(any()); + } + @Test public void testAddBubble() { mBubbleController.updateBubble(mBubbleEntry); @@ -1386,28 +1385,13 @@ public class BubblesTest extends SysuiTestCase { assertStackCollapsed(); } - @Test - public void testRegisterUnregisterComponentCallbacks() { - spyOn(mBubbleControllerContext); - mBubbleController.updateBubble(mBubbleEntry); - verify(mBubbleControllerContext).registerComponentCallbacks(eq(mBubbleController)); - - mBubbleData.dismissBubbleWithKey(mBubbleEntry.getKey(), REASON_APP_CANCEL); - // TODO: not certain why this isn't called normally when tests are run, perhaps because - // it's after an animation in BSV. This calls BubbleController#removeFromWindowManagerMaybe - mBubbleController.onAllBubblesAnimatedOut(); - - verify(mBubbleControllerContext).unregisterComponentCallbacks(eq(mBubbleController)); - } @Test public void testRegisterUnregisterBroadcastListener() { - spyOn(mBubbleControllerContext); + spyOn(mContext); mBubbleController.updateBubble(mBubbleEntry); - verify(mBubbleControllerContext).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), - mFilterArgumentCaptor.capture(), - eq(Context.RECEIVER_EXPORTED)); + verify(mContext).registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), + mFilterArgumentCaptor.capture(), eq(Context.RECEIVER_EXPORTED)); assertThat(mFilterArgumentCaptor.getValue() .hasAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)).isTrue(); assertThat(mFilterArgumentCaptor.getValue() @@ -1418,54 +1402,47 @@ public class BubblesTest extends SysuiTestCase { // it's after an animation in BSV. This calls BubbleController#removeFromWindowManagerMaybe mBubbleController.onAllBubblesAnimatedOut(); - verify(mBubbleControllerContext).unregisterReceiver( - eq(mBroadcastReceiverArgumentCaptor.getValue())); + verify(mContext).unregisterReceiver(eq(mBroadcastReceiverArgumentCaptor.getValue())); } @Test public void testBroadcastReceiverCloseDialogs_notGestureNav() { - spyOn(mBubbleControllerContext); + spyOn(mContext); mBubbleController.updateBubble(mBubbleEntry); mBubbleData.setExpanded(true); - verify(mBubbleControllerContext).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), - mFilterArgumentCaptor.capture(), - eq(Context.RECEIVER_EXPORTED)); + verify(mContext).registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), + mFilterArgumentCaptor.capture(), eq(Context.RECEIVER_EXPORTED)); Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mBubbleControllerContext, i); + mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, i); assertStackExpanded(); } @Test public void testBroadcastReceiverCloseDialogs_reasonGestureNav() { - spyOn(mBubbleControllerContext); + spyOn(mContext); mBubbleController.updateBubble(mBubbleEntry); mBubbleData.setExpanded(true); - verify(mBubbleControllerContext).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), - mFilterArgumentCaptor.capture(), - eq(Context.RECEIVER_EXPORTED)); + verify(mContext).registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), + mFilterArgumentCaptor.capture(), eq(Context.RECEIVER_EXPORTED)); Intent i = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); i.putExtra("reason", "gestureNav"); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mBubbleControllerContext, i); + mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, i); assertStackCollapsed(); } @Test public void testBroadcastReceiver_screenOff() { - spyOn(mBubbleControllerContext); + spyOn(mContext); mBubbleController.updateBubble(mBubbleEntry); mBubbleData.setExpanded(true); - verify(mBubbleControllerContext).registerReceiver( - mBroadcastReceiverArgumentCaptor.capture(), - mFilterArgumentCaptor.capture(), - eq(Context.RECEIVER_EXPORTED)); + verify(mContext).registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), + mFilterArgumentCaptor.capture(), eq(Context.RECEIVER_EXPORTED)); Intent i = new Intent(Intent.ACTION_SCREEN_OFF); - mBroadcastReceiverArgumentCaptor.getValue().onReceive(mBubbleControllerContext, i); + mBroadcastReceiverArgumentCaptor.getValue().onReceive(mContext, i); assertStackCollapsed(); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java index 4b6dd3ef9d62e..5ff57aad9f5d7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.display.DisplayManager; -import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.testing.LeakCheck; @@ -63,10 +62,6 @@ public class SysuiTestableContext extends TestableContext { return (SysuiTestableContext) createDisplayContext(display); } - public SysuiTestableContext createWindowContext(int type, Bundle bundle) { - return new SysuiTestableContext(getBaseContext().createWindowContext(type, bundle)); - } - public void cleanUpReceivers(String testName) { Set copy; synchronized (mRegisteredReceivers) { From 7a2f2a3a1ecb9d5019fea956a0cd3f8574a6b1f0 Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Mon, 15 May 2023 14:38:46 -0700 Subject: [PATCH 2/2] Fix themes of the bubble manage button Still not entirely sure why this is needed. Both of these views get reinflated on theme change, and some of their colors are updated correctly (e.g. font color) but the background color of the drawable is not. Pulling the color from the theme attributes and applying it directly to the background resolves the issue. Bug: 281748524 Test: manual - have a bubble, change the theme, open the bubble, check that the manage menu (and contents of menu) render in the correct theme. Change-Id: I339886d1f1a0ff5b817c106f707518263c67ab07 --- .../com/android/wm/shell/bubbles/BubbleExpandedView.java | 8 +++++++- .../src/com/android/wm/shell/bubbles/BubbleStackView.java | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) 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 adc0c9c4322ae..9fcd207dc3700 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 @@ -46,6 +46,7 @@ import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Picture; import android.graphics.PointF; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.ShapeDrawable; import android.os.RemoteException; @@ -479,13 +480,18 @@ public class BubbleExpandedView extends LinearLayout { void applyThemeAttrs() { final TypedArray ta = mContext.obtainStyledAttributes(new int[]{ android.R.attr.dialogCornerRadius, - com.android.internal.R.attr.materialColorSurfaceBright}); + com.android.internal.R.attr.materialColorSurfaceBright, + com.android.internal.R.attr.materialColorSurfaceContainerHigh}); boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows( mContext.getResources()); mCornerRadius = supportsRoundedCorners ? ta.getDimensionPixelSize(0, 0) : 0; mBackgroundColorFloating = ta.getColor(1, Color.WHITE); mExpandedViewContainer.setBackgroundColor(mBackgroundColorFloating); + final int manageMenuBg = ta.getColor(2, Color.WHITE); ta.recycle(); + if (mManageButton != null) { + mManageButton.getBackground().setColorFilter(manageMenuBg, PorterDuff.Mode.SRC_IN); + } if (mTaskView != null) { mTaskView.setCornerRadius(mCornerRadius); 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 8e9fc1131e4aa..a48be5ed5ad5d 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 @@ -38,8 +38,10 @@ import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Color; import android.graphics.Outline; import android.graphics.PointF; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.ColorDrawable; @@ -1203,6 +1205,12 @@ public class BubbleStackView extends FrameLayout R.layout.bubble_manage_menu, this, false); mManageMenu.setVisibility(View.INVISIBLE); + final TypedArray ta = mContext.obtainStyledAttributes(new int[]{ + com.android.internal.R.attr.materialColorSurfaceBright}); + final int menuBackgroundColor = ta.getColor(0, Color.WHITE); + ta.recycle(); + mManageMenu.getBackground().setColorFilter(menuBackgroundColor, PorterDuff.Mode.SRC_IN); + PhysicsAnimator.getInstance(mManageMenu).setDefaultSpringConfig(mManageSpringConfig); mManageMenu.setOutlineProvider(new ViewOutlineProvider() {