Fix incorrect magnification window size when the dvice is folded

When the foldable is folded /unfolded, we will refetch the display size
to compute the appropriate the window size.

The signal of display size changed is from onConfigurationChanged
which is invoked by Application context. However, we get the display
size from the WindowContxt.

To fix it, we register the callback with the WindowContext based on
the view visiblty, and update the configuration related values before
showing the window.

Test: manual test
      atest com.android.systemui.accessibility
Bug: 213958569
Bug: 214318642
Change-Id: Ic98f782f98b9c29f58d08e064985da731e13aa93
This commit is contained in:
ryanlwlin
2022-01-17 11:46:15 +08:00
parent 189f69261f
commit e216d2dff0
7 changed files with 106 additions and 48 deletions

View File

@@ -22,8 +22,10 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import android.annotation.NonNull;
import android.annotation.UiContext;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -54,7 +56,8 @@ import java.util.Collections;
* The button icon is movable by dragging and it would not overlap navigation bar window.
* And the button UI would automatically be dismissed after displaying for a period of time.
*/
class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureListener {
class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureListener,
ComponentCallbacks {
@VisibleForTesting
static final long FADING_ANIMATION_DURATION_MS = 300;
@@ -75,6 +78,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
private final LayoutParams mParams;
private final SwitchListener mSwitchListener;
private final Configuration mConfiguration;
@VisibleForTesting
final Rect mDraggableWindowBounds = new Rect();
private boolean mIsVisible = false;
@@ -101,6 +105,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
MagnificationModeSwitch(Context context, @NonNull ImageView imageView,
SfVsyncFrameCallbackProvider sfVsyncFrameProvider, SwitchListener switchListener) {
mContext = context;
mConfiguration = new Configuration(context.getResources().getConfiguration());
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mWindowManager = mContext.getSystemService(WindowManager.class);
mSfVsyncFrameProvider = sfVsyncFrameProvider;
@@ -270,6 +275,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
mIsFadeOutAnimating = false;
mImageView.setAlpha(0f);
mWindowManager.removeView(mImageView);
mContext.unregisterComponentCallbacks(this);
mIsVisible = false;
}
@@ -291,6 +297,8 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
mImageView.setImageResource(getIconResId(mode));
}
if (!mIsVisible) {
onConfigurationChanged(mContext.getResources().getConfiguration());
mContext.registerComponentCallbacks(this);
if (resetPosition) {
mDraggableWindowBounds.set(getDraggableWindowBounds());
mParams.x = mDraggableWindowBounds.right;
@@ -321,7 +329,21 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
}
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
final int configDiff = newConfig.diff(mConfiguration);
mConfiguration.setTo(newConfig);
onConfigurationChanged(configDiff);
}
@Override
public void onLowMemory() {
}
void onConfigurationChanged(int configDiff) {
if (configDiff == 0) {
return;
}
if ((configDiff & (ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_SCREEN_SIZE))
!= 0) {
final Rect previousDraggableBounds = new Rect(mDraggableWindowBounds);

View File

@@ -23,7 +23,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_M
import android.annotation.MainThread;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Handler;
@@ -65,7 +64,6 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie
private final OverviewProxyService mOverviewProxyService;
private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl;
private Configuration mLastConfiguration;
private SysUiState mSysUiState;
private static class ControllerSupplier extends
@@ -107,7 +105,6 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie
SysUiState sysUiState, OverviewProxyService overviewProxyService) {
super(context);
mHandler = mainHandler;
mLastConfiguration = new Configuration(context.getResources().getConfiguration());
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mCommandQueue = commandQueue;
mModeSwitchesController = modeSwitchesController;
@@ -117,18 +114,6 @@ public class WindowMagnification extends CoreStartable implements WindowMagnifie
mHandler, this, context.getSystemService(DisplayManager.class), sysUiState);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
final int configDiff = newConfig.diff(mLastConfiguration);
mLastConfiguration.setTo(newConfig);
mMagnificationControllerSupplier.forEach(
magnificationController -> magnificationController.onConfigurationChanged(
configDiff));
if (mModeSwitchesController != null) {
mModeSwitchesController.onConfigurationChanged(configDiff);
}
}
@Override
public void start() {
mCommandQueue.addCallback(this);

View File

@@ -26,6 +26,7 @@ import android.animation.PropertyValuesHolder;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiContext;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -76,7 +77,8 @@ import java.util.Locale;
* Class to handle adding and removing a window magnification.
*/
class WindowMagnificationController implements View.OnTouchListener, SurfaceHolder.Callback,
MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener {
MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener,
ComponentCallbacks {
private static final String TAG = "WindowMagnificationController";
@SuppressWarnings("isloggabletaglength")
@@ -143,6 +145,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private View mTopDrag;
private View mRightDrag;
private View mBottomDrag;
private final Configuration mConfiguration;
@NonNull
private final WindowMagnifierCallback mWindowMagnifierCallback;
@@ -191,6 +194,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mSfVsyncFrameProvider = sfVsyncFrameProvider;
mWindowMagnifierCallback = callback;
mSysUiState = sysUiState;
mConfiguration = new Configuration(context.getResources().getConfiguration());
final Display display = mContext.getDisplay();
mDisplayId = mContext.getDisplayId();
@@ -339,6 +343,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
}
mMirrorViewBounds.setEmpty();
updateSystemUIStateIfNeeded();
mContext.unregisterComponentCallbacks(this);
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
final int configDiff = newConfig.diff(mConfiguration);
mConfiguration.setTo(newConfig);
onConfigurationChanged(configDiff);
}
@Override
public void onLowMemory() {
}
/**
@@ -351,6 +367,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
Log.d(TAG, "onConfigurationChanged = " + Configuration.configurationDiffToString(
configDiff));
}
if (configDiff == 0) {
return;
}
if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
onRotate();
}
@@ -390,7 +409,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
if (currentWindowBounds.equals(oldWindowBounds)) {
if (DEBUG) {
Log.d(TAG, "updateMagnificationFrame -- window bounds is not changed");
Log.d(TAG, "handleScreenSizeChanged -- window bounds is not changed");
}
return false;
}
@@ -851,6 +870,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
deleteWindowMagnification();
return;
}
if (!isWindowVisible()) {
onConfigurationChanged(mResources.getConfiguration());
mContext.registerComponentCallbacks(this);
}
mMagnificationFrameOffsetX = Float.isNaN(magnificationFrameOffsetRatioX)
? mMagnificationFrameOffsetX

View File

@@ -111,6 +111,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = Mockito.spy(getContext());
final WindowManager wm = mContext.getSystemService(WindowManager.class);
mSwitchListener = new SwitchListenerStub();
mWindowManager = spy(new TestableWindowManager(wm));
@@ -139,16 +140,18 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
public void tearDown() {
mFadeOutAnimation = null;
mMotionEventHelper.recycleEvents();
mMagnificationModeSwitch.removeButton();
}
@Test
public void removeButton_buttonIsShowing_removeView() {
public void removeButton_buttonIsShowing_removeViewAndUnregisterComponentCallbacks() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mMagnificationModeSwitch.removeButton();
verify(mWindowManager).removeView(mSpyImageView);
verify(mViewPropertyAnimator).cancel();
verify(mContext).unregisterComponentCallbacks(mMagnificationModeSwitch);
}
@Test
@@ -463,6 +466,13 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
layoutPrams.accessibilityTitle);
}
@Test
public void showButton_registerComponentCallbacks() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
verify(mContext).registerComponentCallbacks(mMagnificationModeSwitch);
}
@Test
public void onLocaleChanged_buttonIsShowing_updateA11yWindowTitle() {
final String newA11yWindowTitle = "new a11y window title";

View File

@@ -91,7 +91,6 @@ public class ModeSwitchesControllerTest extends SysuiTestCase {
verify(mModeSwitch).onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
}
@Test
public void testOnSwitchClick_showWindowModeButton_invokeListener() {
mModeSwitchesController.showButton(Display.DEFAULT_DISPLAY,

View File

@@ -16,6 +16,8 @@
package com.android.systemui.accessibility;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Choreographer.FrameCallback;
import static android.view.WindowInsets.Type.systemGestures;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -45,6 +47,7 @@ import static org.mockito.Mockito.when;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.PointF;
@@ -223,13 +226,9 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
final int screenSize = mContext.getResources().getDimensionPixelSize(
R.dimen.magnification_max_frame_size) * 10;
mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
//We need to initialize new one because the window size is determined when initialization.
final WindowMagnificationController controller = new WindowMagnificationController(mContext,
mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider,
mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState);
mInstrumentation.runOnMainSync(() -> {
controller.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
@@ -242,17 +241,17 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
}
@Test
public void deleteWindowMagnification_destroyControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
public void deleteWindowMagnification_destroyControlAndUnregisterComponentCallback() {
mInstrumentation.runOnMainSync(
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
Float.NaN,
Float.NaN));
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.deleteWindowMagnification();
});
mInstrumentation.runOnMainSync(
() -> mWindowMagnificationController.deleteWindowMagnification());
verify(mMirrorWindowControl).destroyControl();
verify(mContext).unregisterComponentCallbacks(mWindowMagnificationController);
}
@Test
@@ -322,11 +321,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
@Test
public void onOrientationChanged_enabled_updateDisplayRotationAndCenterStayAtSamePosition() {
final Display display = Mockito.spy(mContext.getDisplay());
final int currentRotation = display.getRotation();
final int newRotation = (currentRotation + 1) % 4;
when(display.getRotation()).thenReturn(newRotation);
when(mContext.getDisplay()).thenReturn(display);
final int newRotation = simulateRotateTheDevice();
final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
final float center = Math.min(windowBounds.exactCenterX(), windowBounds.exactCenterY());
final float displayWidth = windowBounds.width();
@@ -534,6 +529,30 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
assertEquals(Float.NaN, mWindowMagnificationController.getScale(), 0);
}
@Test
public void enableWindowMagnification_rotationIsChanged_updateRotationValue() {
final Configuration config = mContext.getResources().getConfiguration();
config.orientation = config.orientation == ORIENTATION_LANDSCAPE ? ORIENTATION_PORTRAIT
: ORIENTATION_LANDSCAPE;
final int newRotation = simulateRotateTheDevice();
mInstrumentation.runOnMainSync(
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
Float.NaN, Float.NaN));
assertEquals(newRotation, mWindowMagnificationController.mRotation);
}
@Test
public void enableWindowMagnification_registerComponentCallback() {
mInstrumentation.runOnMainSync(
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
Float.NaN,
Float.NaN));
verify(mContext).registerComponentCallbacks(mWindowMagnificationController);
}
@Test
public void onLocaleChanged_enabled_updateA11yWindowTitle() {
final String newA11yWindowTitle = "new a11y window title";
@@ -610,4 +629,14 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
.build();
mWindowManager.setWindowInsets(testInsets);
}
@Surface.Rotation
private int simulateRotateTheDevice() {
final Display display = Mockito.spy(mContext.getDisplay());
final int currentRotation = display.getRotation();
final int newRotation = (currentRotation + 1) % 4;
when(display.getRotation()).thenReturn(newRotation);
when(mContext.getDisplay()).thenReturn(display);
return newRotation;
}
}

View File

@@ -30,7 +30,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.RemoteException;
@@ -158,15 +157,6 @@ public class WindowMagnificationTest extends SysuiTestCase {
verify(mConnectionCallback).onDrag(TEST_DISPLAY);
}
@Test
public void onConfigurationChanged_updateModeSwitches() {
final Configuration config = new Configuration();
config.densityDpi = Configuration.DENSITY_DPI_ANY;
mWindowMagnification.onConfigurationChanged(config);
verify(mModeSwitchesController).onConfigurationChanged(anyInt());
}
@Test
public void overviewProxyIsConnected_noController_resetFlag() {
mOverviewProxyListener.onConnectionChanged(true);