Merge "Fix incorrect boundary/appearance after folding the device" into sc-v2-dev
This commit is contained in:
@@ -28,6 +28,7 @@ import android.annotation.Nullable;
|
||||
import android.annotation.UiContext;
|
||||
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.Matrix;
|
||||
@@ -35,6 +36,7 @@ import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
@@ -76,6 +78,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
MirrorWindowControl.MirrorWindowDelegate, MagnificationGestureDetector.OnGestureListener {
|
||||
|
||||
private static final String TAG = "WindowMagnificationController";
|
||||
@SuppressWarnings("isloggabletaglength")
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG) || Build.IS_DEBUGGABLE;
|
||||
// Delay to avoid updating state description too frequently.
|
||||
private static final int UPDATE_STATE_DESCRIPTION_DELAY_MS = 100;
|
||||
// It should be consistent with the value defined in WindowMagnificationGestureHandler.
|
||||
@@ -158,14 +162,15 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
mRotation = display.getRotation();
|
||||
|
||||
mWm = context.getSystemService(WindowManager.class);
|
||||
mWindowBounds = mWm.getCurrentWindowMetrics().getBounds();
|
||||
mWindowBounds = new Rect(mWm.getCurrentWindowMetrics().getBounds());
|
||||
|
||||
mResources = mContext.getResources();
|
||||
mScale = mResources.getInteger(R.integer.magnification_default_scale);
|
||||
mBounceEffectDuration = mResources.getInteger(
|
||||
com.android.internal.R.integer.config_shortAnimTime);
|
||||
updateDimensions();
|
||||
setInitialStartBounds();
|
||||
setMagnificationFrameWith(mWindowBounds, mWindowBounds.width() / 2,
|
||||
mWindowBounds.height() / 2);
|
||||
computeBounceAnimationScale();
|
||||
|
||||
mMirrorWindowControl = mirrorWindowControl;
|
||||
@@ -286,18 +291,59 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
* @param configDiff a bit mask of the differences between the configurations
|
||||
*/
|
||||
void onConfigurationChanged(int configDiff) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onConfigurationChanged = " + Configuration.configurationDiffToString(
|
||||
configDiff));
|
||||
}
|
||||
if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
|
||||
onRotate();
|
||||
}
|
||||
|
||||
if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
|
||||
updateAccessibilityWindowTitleIfNeeded();
|
||||
}
|
||||
|
||||
boolean reCreateWindow = false;
|
||||
if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
|
||||
updateDimensions();
|
||||
computeBounceAnimationScale();
|
||||
if (isWindowVisible()) {
|
||||
deleteWindowMagnification();
|
||||
enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
|
||||
}
|
||||
} else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
|
||||
onRotate();
|
||||
} else if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
|
||||
updateAccessibilityWindowTitleIfNeeded();
|
||||
reCreateWindow = true;
|
||||
}
|
||||
|
||||
if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
|
||||
reCreateWindow |= handleScreenSizeChanged();
|
||||
}
|
||||
|
||||
// Recreate the window again to correct the window appearance due to density or
|
||||
// window size changed not caused by rotation.
|
||||
if (isWindowVisible() && reCreateWindow) {
|
||||
deleteWindowMagnification();
|
||||
enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the magnification frame if the window bounds is changed.
|
||||
* Note that the orientation also changes the wind bounds, so it should be handled first.
|
||||
*
|
||||
* @return {@code true} if the magnification frame is changed with the new window bounds.
|
||||
*/
|
||||
private boolean handleScreenSizeChanged() {
|
||||
final Rect oldWindowBounds = new Rect(mWindowBounds);
|
||||
final Rect currentWindowBounds = mWm.getCurrentWindowMetrics().getBounds();
|
||||
|
||||
if (currentWindowBounds.equals(oldWindowBounds)) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateMagnificationFrame -- window bounds is not changed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
mWindowBounds.set(currentWindowBounds);
|
||||
final float newCenterX = (getCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
|
||||
final float newCenterY = (getCenterY()) * mWindowBounds.height() / oldWindowBounds.height();
|
||||
setMagnificationFrameWith(mWindowBounds, (int) newCenterX, (int) newCenterY);
|
||||
calculateMagnificationFrameBoundary();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateSystemUIStateIfNeeded() {
|
||||
@@ -311,30 +357,42 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
mWm.updateViewLayout(mMirrorView, params);
|
||||
}
|
||||
|
||||
/** Handles MirrorWindow position when the device rotation changed. */
|
||||
/**
|
||||
* Keep MirrorWindow position on the screen unchanged when device rotates 90° clockwise or
|
||||
* anti-clockwise.
|
||||
*/
|
||||
private void onRotate() {
|
||||
final Display display = mContext.getDisplay();
|
||||
final int oldRotation = mRotation;
|
||||
mWindowBounds = mWm.getCurrentWindowMetrics().getBounds();
|
||||
|
||||
setMagnificationFrameBoundary();
|
||||
mRotation = display.getRotation();
|
||||
final int rotationDegree = getDegreeFromRotation(mRotation, oldRotation);
|
||||
if (rotationDegree == 0 || rotationDegree == 180) {
|
||||
Log.w(TAG, "onRotate -- rotate with the device. skip it");
|
||||
return;
|
||||
}
|
||||
final Rect currentWindowBounds = new Rect(mWm.getCurrentWindowMetrics().getBounds());
|
||||
if (currentWindowBounds.width() != mWindowBounds.height()
|
||||
|| currentWindowBounds.height() != mWindowBounds.width()) {
|
||||
Log.w(TAG, "onRotate -- unexpected window height/width");
|
||||
return;
|
||||
}
|
||||
|
||||
mWindowBounds.set(currentWindowBounds);
|
||||
|
||||
calculateMagnificationFrameBoundary();
|
||||
|
||||
if (!isWindowVisible()) {
|
||||
return;
|
||||
}
|
||||
// Keep MirrorWindow position on the screen unchanged when device rotates 90°
|
||||
// clockwise or anti-clockwise.
|
||||
final int rotationDegree = getDegreeFromRotation(mRotation, oldRotation);
|
||||
|
||||
final Matrix matrix = new Matrix();
|
||||
matrix.setRotate(rotationDegree);
|
||||
if (rotationDegree == 90) {
|
||||
matrix.postTranslate(mWindowBounds.width(), 0);
|
||||
} else if (rotationDegree == 270) {
|
||||
matrix.postTranslate(0, mWindowBounds.height());
|
||||
} else {
|
||||
Log.w(TAG, "Invalid rotation change. " + rotationDegree);
|
||||
return;
|
||||
}
|
||||
// The rect of MirrorView is going to be transformed.
|
||||
LayoutParams params =
|
||||
@@ -440,12 +498,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
}
|
||||
}
|
||||
|
||||
private void setInitialStartBounds() {
|
||||
private void setMagnificationFrameWith(Rect windowBounds, int centerX, int centerY) {
|
||||
// Sets the initial frame area for the mirror and places it in the center of the display.
|
||||
final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 2
|
||||
final int initSize = Math.min(windowBounds.width(), windowBounds.height()) / 2
|
||||
+ 2 * mMirrorSurfaceMargin;
|
||||
final int initX = mWindowBounds.width() / 2 - initSize / 2;
|
||||
final int initY = mWindowBounds.height() / 2 - initSize / 2;
|
||||
final int initX = centerX - initSize / 2;
|
||||
final int initY = centerY - initSize / 2;
|
||||
mMagnificationFrame.set(initX, initY, initX + initSize, initY + initSize);
|
||||
}
|
||||
|
||||
@@ -553,7 +611,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
mSourceBounds.set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
private void setMagnificationFrameBoundary() {
|
||||
private void calculateMagnificationFrameBoundary() {
|
||||
// Calculates width and height for magnification frame could exceed out the screen.
|
||||
// TODO : re-calculating again when scale is changed.
|
||||
// The half width of magnification frame.
|
||||
@@ -644,7 +702,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
: centerY - mMagnificationFrame.exactCenterY();
|
||||
mScale = Float.isNaN(scale) ? mScale : scale;
|
||||
|
||||
setMagnificationFrameBoundary();
|
||||
calculateMagnificationFrameBoundary();
|
||||
updateMagnificationFramePosition((int) offsetX, (int) offsetY);
|
||||
if (!isWindowVisible()) {
|
||||
createMirrorWindow();
|
||||
@@ -764,6 +822,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
pw.println(" mOverlapWithGestureInsets:" + mOverlapWithGestureInsets);
|
||||
pw.println(" mScale:" + mScale);
|
||||
pw.println(" mMirrorViewBounds:" + (isWindowVisible() ? mMirrorViewBounds : "empty"));
|
||||
pw.println(" mSourceBounds:"
|
||||
+ (isWindowVisible() ? mSourceBounds : "empty"));
|
||||
pw.println(" mSystemGestureTop:" + mSystemGestureTop);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package com.android.systemui.accessibility;
|
||||
|
||||
import static android.view.WindowInsets.Type.systemGestures;
|
||||
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.Display;
|
||||
@@ -79,14 +76,11 @@ public class TestableWindowManager implements WindowManager {
|
||||
|
||||
@Override
|
||||
public WindowMetrics getCurrentWindowMetrics() {
|
||||
final Insets systemGesturesInsets = Insets.of(0, 0, 0, 10);
|
||||
final WindowInsets insets = new WindowInsets.Builder()
|
||||
.setInsets(systemGestures(), systemGesturesInsets)
|
||||
.build();
|
||||
final WindowMetrics realMetrics = mWindowManager.getCurrentWindowMetrics();
|
||||
final WindowMetrics windowMetrics = new WindowMetrics(
|
||||
mWindowBounds == null ? mWindowManager.getCurrentWindowMetrics().getBounds()
|
||||
mWindowBounds == null ? realMetrics.getBounds()
|
||||
: mWindowBounds,
|
||||
mWindowInsets == null ? insets : mWindowInsets);
|
||||
mWindowInsets == null ? realMetrics.getWindowInsets() : mWindowInsets);
|
||||
return windowMetrics;
|
||||
}
|
||||
|
||||
@@ -106,10 +100,20 @@ public class TestableWindowManager implements WindowManager {
|
||||
return (WindowManager.LayoutParams) mView.getLayoutParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given window bounds to current window metrics.
|
||||
*
|
||||
* @param bounds the window bounds
|
||||
*/
|
||||
public void setWindowBounds(Rect bounds) {
|
||||
mWindowBounds = bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given window insets to the current window metics.
|
||||
*
|
||||
* @param insets the window insets.
|
||||
*/
|
||||
public void setWindowInsets(WindowInsets insets) {
|
||||
mWindowInsets = insets;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.accessibility;
|
||||
|
||||
import static android.view.Choreographer.FrameCallback;
|
||||
import static android.view.WindowInsets.Type.systemGestures;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
|
||||
@@ -45,6 +46,8 @@ import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
@@ -55,6 +58,7 @@ import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
@@ -239,11 +243,13 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION);
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_SCREEN_SIZE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onOrientationChanged_enabled_updateDisplayRotationAndLayout() {
|
||||
public void onOrientationChanged_enabled_updateDisplayRotationAndCenterStayAtSamePosition() {
|
||||
final Display display = Mockito.spy(mContext.getDisplay());
|
||||
when(display.getRotation()).thenReturn(Surface.ROTATION_90);
|
||||
when(mContext.getDisplay()).thenReturn(display);
|
||||
@@ -251,13 +257,22 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
|
||||
Float.NaN);
|
||||
});
|
||||
final PointF expectedCenter = new PointF(mWindowMagnificationController.getCenterY(),
|
||||
mWindowMagnificationController.getCenterX());
|
||||
final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
|
||||
// Rotate the window 90 degrees.
|
||||
windowBounds.set(windowBounds.top, windowBounds.left, windowBounds.bottom,
|
||||
windowBounds.right);
|
||||
mWindowManager.setWindowBounds(windowBounds);
|
||||
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION);
|
||||
});
|
||||
|
||||
assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation);
|
||||
// The first invocation is called when the surface is created.
|
||||
final PointF actualCenter = new PointF(mWindowMagnificationController.getCenterX(),
|
||||
mWindowMagnificationController.getCenterY());
|
||||
assertEquals(expectedCenter, actualCenter);
|
||||
verify(mWindowManager, times(2)).updateViewLayout(any(), any());
|
||||
}
|
||||
|
||||
@@ -274,6 +289,33 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScreenSizeChanged_enabledAtTheCenterOfScreen_keepSameWindowSizeRatio() {
|
||||
// The default position is at the center of the screen.
|
||||
final float expectedRatio = 0.5f;
|
||||
final Rect testWindowBounds = new Rect(
|
||||
mWindowManager.getCurrentWindowMetrics().getBounds());
|
||||
testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
|
||||
testWindowBounds.right + 100, testWindowBounds.bottom + 100);
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
|
||||
Float.NaN);
|
||||
});
|
||||
mWindowManager.setWindowBounds(testWindowBounds);
|
||||
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_SCREEN_SIZE);
|
||||
});
|
||||
|
||||
// The ratio of center to window size should be the same.
|
||||
assertEquals(expectedRatio,
|
||||
mWindowMagnificationController.getCenterX() / testWindowBounds.width(),
|
||||
0);
|
||||
assertEquals(expectedRatio,
|
||||
mWindowMagnificationController.getCenterY() / testWindowBounds.height(),
|
||||
0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
@@ -419,9 +461,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moveWindowMagnificationToTheBottom_enabled_overlapFlagIsTrue() {
|
||||
final WindowManager wm = mContext.getSystemService(WindowManager.class);
|
||||
final Rect bounds = wm.getCurrentWindowMetrics().getBounds();
|
||||
public void moveWindowMagnificationToTheBottom_enabledWithGestureInset_overlapFlagIsTrue() {
|
||||
final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
|
||||
final WindowInsets testInsets = new WindowInsets.Builder()
|
||||
.setInsets(systemGestures(), Insets.of(0, 0, 0, 10))
|
||||
.build();
|
||||
mWindowManager.setWindowInsets(testInsets);
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
|
||||
Float.NaN);
|
||||
|
||||
Reference in New Issue
Block a user