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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user