Merge changes I339886d1,Id53bfc8c into udc-dev am: 7f4445dfd1 am: 5cb37f47d8 am: 9c4319e4df am: ce079d1ab5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23242775

Change-Id: I277466575dcf833888af082444e53a92451bf80d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
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 6986810..3eb9fa2 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.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.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.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.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 @@
  *
  * The controller manages addition, removal, and visible state of bubbles on screen.
  */
-public class BubbleController implements ComponentCallbacks2,
+public class BubbleController implements ConfigurationChangeListener,
         RemoteCallable<BubbleController> {
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES;
@@ -159,6 +153,7 @@
     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 @@
     /** 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 @@
             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 @@
         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 @@
         }
         mCurrentProfiles = userProfiles;
 
+        mShellController.addConfigurationChangeListener(this);
         mShellController.addExternalInterface(KEY_EXTRA_SHELL_BUBBLES,
                 this::createExternalInterface, this);
         mShellCommandHandler.addDumpCallback(this::dump, this);
@@ -779,7 +774,6 @@
         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 @@
         // 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 @@
         mSavedUserBubbleData.remove(userId);
     }
 
-    private void onThemeChanged() {
+    @Override
+    public void onThemeChanged() {
         if (mStackView != null) {
             mStackView.onThemeChanged();
         }
@@ -969,60 +963,34 @@
         }
     }
 
-    // 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/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index adc0c9c..9fcd207 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.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 @@
     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 8e9fc11..a48be5e 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.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 @@
                 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() {
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 f0683a4..47a86b1 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 @@
 
     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 @@
         // Get a reference to KeyguardStateController.Callback
         verify(mKeyguardStateController, atLeastOnce())
                 .addCallback(mKeyguardStateControllerCallbackCaptor.capture());
-
-        mBubbleControllerContext = mBubbleController.getContext();
     }
 
     @After
@@ -474,6 +468,11 @@
     }
 
     @Test
+    public void instantiateController_registerConfigChangeListener() {
+        verify(mShellController, times(1)).addConfigurationChangeListener(any());
+    }
+
+    @Test
     public void testAddBubble() {
         mBubbleController.updateBubble(mBubbleEntry);
         assertTrue(mBubbleController.hasBubbles());
@@ -1386,28 +1385,13 @@
         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 @@
         // 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 4b6dd3e..5ff57aa 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.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 @@
         return (SysuiTestableContext) createDisplayContext(display);
     }
 
-    public SysuiTestableContext createWindowContext(int type, Bundle bundle) {
-        return new SysuiTestableContext(getBaseContext().createWindowContext(type, bundle));
-    }
-
     public void cleanUpReceivers(String testName) {
         Set<BroadcastReceiver> copy;
         synchronized (mRegisteredReceivers) {