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 4b037214fcdd2..6a0f061923599 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 @@ -52,6 +52,7 @@ import android.content.pm.UserInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.PointF; +import android.graphics.Rect; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -70,6 +71,7 @@ import android.util.SparseSetArray; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.window.WindowContainerTransaction; import androidx.annotation.MainThread; import androidx.annotation.Nullable; @@ -79,6 +81,8 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; +import com.android.wm.shell.common.DisplayChangeController; +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.TaskStackListenerCallback; @@ -131,6 +135,7 @@ public class BubbleController { private final WindowManager mWindowManager; private final TaskStackListenerImpl mTaskStackListener; private final ShellTaskOrganizer mTaskOrganizer; + private final DisplayController mDisplayController; // Used to post to main UI thread private final ShellExecutor mMainExecutor; @@ -171,25 +176,21 @@ public class BubbleController { /** Whether or not the BubbleStackView has been added to the WindowManager. */ private boolean mAddedToWindowManager = false; - /** Last known orientation, used to detect orientation changes in {@link #onConfigChanged}. */ - private int mOrientation = Configuration.ORIENTATION_UNDEFINED; - - /** - * Last known screen density, used to detect display size changes in {@link #onConfigChanged}. - */ + /** Saved screen density, used to detect display size changes in {@link #onConfigChanged}. */ private int mDensityDpi = Configuration.DENSITY_DPI_UNDEFINED; - /** - * Last known font scale, used to detect font size changes in {@link #onConfigChanged}. - */ + /** 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; - /** Last known direction, used to detect layout direction changes @link #onConfigChanged}. */ + /** Saved direction, used to detect layout direction changes @link #onConfigChanged}. */ private int mLayoutDirection = View.LAYOUT_DIRECTION_UNDEFINED; private boolean mInflateSynchronously; - /** true when user is in status bar unlock shade. */ + /** True when user is in status bar unlock shade. */ private boolean mIsStatusBarShade = true; /** @@ -205,6 +206,7 @@ public class BubbleController { TaskStackListenerImpl taskStackListener, UiEventLogger uiEventLogger, ShellTaskOrganizer organizer, + DisplayController displayController, ShellExecutor mainExecutor, Handler mainHandler) { BubbleLogger logger = new BubbleLogger(uiEventLogger); @@ -213,7 +215,8 @@ public class BubbleController { return new BubbleController(context, data, synchronizer, floatingContentCoordinator, new BubbleDataRepository(context, launcherApps, mainExecutor), statusBarService, windowManager, windowManagerShellWrapper, launcherApps, - logger, taskStackListener, organizer, positioner, mainExecutor, mainHandler); + logger, taskStackListener, organizer, positioner, displayController, mainExecutor, + mainHandler); } /** @@ -233,6 +236,7 @@ public class BubbleController { TaskStackListenerImpl taskStackListener, ShellTaskOrganizer organizer, BubblePositioner positioner, + DisplayController displayController, ShellExecutor mainExecutor, Handler mainHandler) { mContext = context; @@ -256,6 +260,7 @@ public class BubbleController { mBubbleData = data; mSavedBubbleKeysPerUser = new SparseSetArray<>(); mBubbleIconFactory = new BubbleIconFactory(context); + mDisplayController = displayController; } public void initialize() { @@ -287,7 +292,6 @@ public class BubbleController { e.printStackTrace(); } - mBubbleData.setCurrentUserId(mCurrentUserId); mTaskOrganizer.addLocusIdListener((taskId, locus, visible) -> @@ -366,6 +370,23 @@ public class BubbleController { } } }); + + mDisplayController.addDisplayChangingController( + new DisplayChangeController.OnDisplayChangingListener() { + @Override + public void onRotateDisplay(int displayId, int fromRotation, int toRotation, + WindowContainerTransaction t) { + // This is triggered right before the rotation is applied + if (fromRotation != toRotation) { + mBubblePositioner.setRotation(toRotation); + if (mStackView != null) { + // Layout listener set on stackView will update the positioner + // once the rotation is applied + mStackView.onOrientationChanged(); + } + } + } + }); } @VisibleForTesting @@ -585,7 +606,7 @@ public class BubbleController { mStackView.addView(mBubbleScrim); mWindowManager.addView(mStackView, mWmLayoutParams); // Position info is dependent on us being attached to a window - mBubblePositioner.update(mOrientation); + mBubblePositioner.update(); } catch (IllegalStateException e) { // This means the stack has already been added. This shouldn't happen... e.printStackTrace(); @@ -682,16 +703,13 @@ public class BubbleController { private void onConfigChanged(Configuration newConfig) { if (mBubblePositioner != null) { - // This doesn't trigger any changes, always update it - mBubblePositioner.update(newConfig.orientation); + mBubblePositioner.update(); } if (mStackView != null && newConfig != null) { - if (newConfig.orientation != mOrientation) { - mOrientation = newConfig.orientation; - mStackView.onOrientationChanged(); - } - if (newConfig.densityDpi != mDensityDpi) { + if (newConfig.densityDpi != mDensityDpi + || !newConfig.windowConfiguration.getBounds().equals(mScreenBounds)) { mDensityDpi = newConfig.densityDpi; + mScreenBounds.set(newConfig.windowConfiguration.getBounds()); mBubbleIconFactory = new BubbleIconFactory(mContext); mStackView.onDisplaySizeChanged(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java index 1562e4bf6fcc3..a81c2d8bef0ae 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java @@ -20,13 +20,13 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.content.Context; -import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Insets; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.util.Log; +import android.view.Surface; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; @@ -65,7 +65,7 @@ public class BubblePositioner { private Context mContext; private WindowManager mWindowManager; private Rect mPositionRect; - private int mOrientation; + private @Surface.Rotation int mRotation = Surface.ROTATION_0; private Insets mInsets; private int mBubbleSize; @@ -82,14 +82,18 @@ public class BubblePositioner { public BubblePositioner(Context context, WindowManager windowManager) { mContext = context; mWindowManager = windowManager; - update(Configuration.ORIENTATION_UNDEFINED); + update(); + } + + public void setRotation(int rotation) { + mRotation = rotation; } /** - * Updates orientation, available space, and inset information. Call this when config changes + * Available space and inset information. Call this when config changes * occur or when added to a window. */ - public void update(int orientation) { + public void update() { WindowMetrics windowMetrics = mWindowManager.getCurrentWindowMetrics(); if (windowMetrics == null) { return; @@ -102,12 +106,12 @@ public class BubblePositioner { if (BubbleDebugConfig.DEBUG_POSITIONER) { Log.w(TAG, "update positioner:" - + " landscape= " + (orientation == Configuration.ORIENTATION_LANDSCAPE) + + " rotation= " + mRotation + " insets: " + insets + " bounds: " + windowMetrics.getBounds() + " showingInTaskbar: " + mShowingInTaskbar); } - updateInternal(orientation, insets, windowMetrics.getBounds()); + updateInternal(mRotation, insets, windowMetrics.getBounds()); } /** @@ -122,12 +126,12 @@ public class BubblePositioner { mTaskbarIconSize = iconSize; mTaskbarPosition = taskbarPosition; mTaskbarSize = taskbarSize; - update(mOrientation); + update(); } @VisibleForTesting - public void updateInternal(int orientation, Insets insets, Rect bounds) { - mOrientation = orientation; + public void updateInternal(int rotation, Insets insets, Rect bounds) { + mRotation = rotation; mInsets = insets; mPositionRect = new Rect(bounds); @@ -189,7 +193,7 @@ public class BubblePositioner { * @return whether the device is in landscape orientation. */ public boolean isLandscape() { - return mOrientation == Configuration.ORIENTATION_LANDSCAPE; + return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270; } /** @@ -200,8 +204,7 @@ public class BubblePositioner { * to the left or right side. */ public boolean showBubblesVertically() { - return mOrientation == Configuration.ORIENTATION_LANDSCAPE - || mShowingInTaskbar; + return isLandscape() || mShowingInTaskbar; } /** Size of the bubble account for badge & dot. */ 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 64bd245cb2eec..6719d747c5b9b 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 @@ -884,6 +884,7 @@ public class BubbleStackView extends FrameLayout mOrientationChangedListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + mPositioner.update(); onDisplaySizeChanged(); mExpandedAnimationController.updateResources(); mStackAnimationController.updateResources(); @@ -1214,11 +1215,12 @@ public class BubbleStackView extends FrameLayout updateExpandedViewTheme(); } - /** Respond to the phone being rotated by repositioning the stack and hiding any flyouts. */ + /** + * Respond to the phone being rotated by repositioning the stack and hiding any flyouts. + * This is called prior to the rotation occurring, any values that should be updated + * based on the new rotation should occur in {@link #mOrientationChangedListener}. + */ public void onOrientationChanged() { - Resources res = getContext().getResources(); - mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top); - mRelativeStackPositionBeforeRotation = new RelativeStackPosition( mPositioner.getRestingPosition(), mStackAnimationController.getAllowableStackPositionRegion()); @@ -1261,6 +1263,10 @@ public class BubbleStackView extends FrameLayout mStackAnimationController.updateResources(); mDismissView.updateResources(); mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2); + mStackAnimationController.setStackPosition( + new RelativeStackPosition( + mPositioner.getRestingPosition(), + mStackAnimationController.getAllowableStackPositionRegion())); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 4c9ba66c1e390..26b68afed4949 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -190,12 +190,13 @@ public abstract class WMShellBaseModule { TaskStackListenerImpl taskStackListener, UiEventLogger uiEventLogger, ShellTaskOrganizer organizer, + DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) { return Optional.of(BubbleController.create(context, null /* synchronizer */, floatingContentCoordinator, statusBarService, windowManager, windowManagerShellWrapper, launcherApps, taskStackListener, - uiEventLogger, organizer, mainExecutor, mainHandler)); + uiEventLogger, organizer, displayController, mainExecutor, mainHandler)); } // 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 9fc1df73d8b35..6e2e4cb9ecfa9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -112,6 +112,7 @@ import com.android.wm.shell.bubbles.BubbleOverflow; 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.common.DisplayController; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; @@ -315,6 +316,7 @@ public class BubblesTest extends SysuiTestCase { mTaskStackListener, mShellTaskOrganizer, mPositioner, + mock(DisplayController.class), syncExecutor, mock(Handler.class)); mBubbleController.setExpandListener(mBubbleExpandListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java index 89825d240ec1c..9339f81940d9c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java @@ -92,6 +92,7 @@ import com.android.wm.shell.bubbles.BubbleLogger; import com.android.wm.shell.bubbles.BubbleOverflow; import com.android.wm.shell.bubbles.BubbleStackView; import com.android.wm.shell.bubbles.Bubbles; +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.TaskStackListenerImpl; @@ -259,6 +260,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase { mTaskStackListener, mShellTaskOrganizer, mPositioner, + mock(DisplayController.class), syncExecutor, mock(Handler.class)); mBubbleController.setExpandListener(mBubbleExpandListener); 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 a9a558dca5771..cd5aa9a3f9dc6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java @@ -29,6 +29,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.common.DisplayController; import com.android.wm.shell.common.FloatingContentCoordinator; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; @@ -51,12 +52,13 @@ public class TestableBubbleController extends BubbleController { TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, BubblePositioner positioner, + DisplayController displayController, ShellExecutor shellMainExecutor, Handler shellMainHandler) { super(context, data, Runnable::run, floatingContentCoordinator, dataRepository, statusBarService, windowManager, windowManagerShellWrapper, launcherApps, - bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, shellMainExecutor, - shellMainHandler); + bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, displayController, + shellMainExecutor, shellMainHandler); setInflateSynchronously(true); initialize(); }