Merge "Support set window size API" into tm-dev
This commit is contained in:
@@ -606,6 +606,9 @@
|
||||
<!-- The padding ratio of the Accessibility icon foreground drawable -->
|
||||
<item name="accessibility_icon_foreground_padding_ratio" type="dimen">21.88%</item>
|
||||
|
||||
<!-- The minimum window size of the accessibility window magnifier -->
|
||||
<dimen name="accessibility_window_magnifier_min_size">122dp</dimen>
|
||||
|
||||
<!-- Margin around the various security views -->
|
||||
<dimen name="keyguard_muliuser_selector_margin">8dp</dimen>
|
||||
|
||||
|
||||
@@ -4399,6 +4399,7 @@
|
||||
<java-symbol type="color" name="accessibility_focus_highlight_color" />
|
||||
<!-- Width of the outline stroke used by the accessibility focus rectangle -->
|
||||
<java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
|
||||
<java-symbol type="dimen" name="accessibility_window_magnifier_min_size" />
|
||||
|
||||
<java-symbol type="bool" name="config_attachNavBarToAppDuringTransition" />
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.Range;
|
||||
import android.util.Size;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Display;
|
||||
import android.view.Gravity;
|
||||
@@ -62,6 +63,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
|
||||
|
||||
import androidx.core.math.MathUtils;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.systemui.R;
|
||||
@@ -166,6 +169,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
private final Rect mMagnificationFrameBoundary = new Rect();
|
||||
// The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid.
|
||||
private int mSystemGestureTop = -1;
|
||||
private int mMinWindowSize;
|
||||
|
||||
private final WindowMagnificationAnimationController mAnimationController;
|
||||
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
|
||||
@@ -208,8 +212,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
mBounceEffectDuration = mResources.getInteger(
|
||||
com.android.internal.R.integer.config_shortAnimTime);
|
||||
updateDimensions();
|
||||
setMagnificationFrameWith(mWindowBounds, mWindowBounds.width() / 2,
|
||||
mWindowBounds.height() / 2);
|
||||
|
||||
final Size windowSize = getDefaultWindowSizeWithWindowBounds(mWindowBounds);
|
||||
setMagnificationFrame(windowSize.getWidth(), windowSize.getHeight(),
|
||||
mWindowBounds.width() / 2, mWindowBounds.height() / 2);
|
||||
computeBounceAnimationScale();
|
||||
|
||||
mMirrorWindowControl = mirrorWindowControl;
|
||||
@@ -281,6 +287,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
R.dimen.magnification_drag_view_size);
|
||||
mOuterBorderSize = mResources.getDimensionPixelSize(
|
||||
R.dimen.magnification_outer_border_margin);
|
||||
mMinWindowSize = mResources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
|
||||
}
|
||||
|
||||
private void computeBounceAnimationScale() {
|
||||
@@ -414,9 +422,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
return false;
|
||||
}
|
||||
mWindowBounds.set(currentWindowBounds);
|
||||
final Size windowSize = getDefaultWindowSizeWithWindowBounds(mWindowBounds);
|
||||
final float newCenterX = (getCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
|
||||
final float newCenterY = (getCenterY()) * mWindowBounds.height() / oldWindowBounds.height();
|
||||
setMagnificationFrameWith(mWindowBounds, (int) newCenterX, (int) newCenterY);
|
||||
|
||||
setMagnificationFrame(windowSize.getWidth(), windowSize.getHeight(), (int) newCenterX,
|
||||
(int) newCenterY);
|
||||
calculateMagnificationFrameBoundary();
|
||||
return true;
|
||||
}
|
||||
@@ -454,11 +465,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
|
||||
mWindowBounds.set(currentWindowBounds);
|
||||
|
||||
calculateMagnificationFrameBoundary();
|
||||
|
||||
if (!isWindowVisible()) {
|
||||
return;
|
||||
}
|
||||
// Keep MirrorWindow position on the screen unchanged when device rotates 90°
|
||||
// clockwise or anti-clockwise.
|
||||
|
||||
@@ -469,14 +475,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
} else if (rotationDegree == 270) {
|
||||
matrix.postTranslate(0, mWindowBounds.height());
|
||||
}
|
||||
// The rect of MirrorView is going to be transformed.
|
||||
LayoutParams params =
|
||||
(LayoutParams) mMirrorView.getLayoutParams();
|
||||
mTmpRect.set(params.x, params.y, params.x + params.width, params.y + params.height);
|
||||
final RectF transformedRect = new RectF(mTmpRect);
|
||||
|
||||
final RectF transformedRect = new RectF(mMagnificationFrame);
|
||||
// The window frame is going to be transformed by the rotation matrix.
|
||||
transformedRect.inset(-mMirrorSurfaceMargin, -mMirrorSurfaceMargin);
|
||||
matrix.mapRect(transformedRect);
|
||||
moveWindowMagnifier(transformedRect.left - mTmpRect.left,
|
||||
transformedRect.top - mTmpRect.top);
|
||||
setWindowSizeAndCenter((int) transformedRect.width(), (int) transformedRect.height(),
|
||||
(int) transformedRect.centerX(), (int) transformedRect.centerY());
|
||||
}
|
||||
|
||||
/** Returns the rotation degree change of two {@link Surface.Rotation} */
|
||||
@@ -573,16 +578,52 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
}
|
||||
}
|
||||
|
||||
private void setMagnificationFrameWith(Rect windowBounds, int centerX, int centerY) {
|
||||
/**
|
||||
* Sets the window size with given width and height in pixels without changing the
|
||||
* window center. The width or the height will be clamped in the range
|
||||
* [{@link #mMinWindowSize}, screen width or height].
|
||||
*
|
||||
* @param width the window width in pixels
|
||||
* @param height the window height in pixels.
|
||||
*/
|
||||
public void setWindowSize(int width, int height) {
|
||||
setWindowSizeAndCenter(width, height, Float.NaN, Float.NaN);
|
||||
}
|
||||
|
||||
void setWindowSizeAndCenter(int width, int height, float centerX, float centerY) {
|
||||
width = MathUtils.clamp(width, mMinWindowSize, mWindowBounds.width());
|
||||
height = MathUtils.clamp(height, mMinWindowSize, mWindowBounds.height());
|
||||
|
||||
if (Float.isNaN(centerX)) {
|
||||
centerX = mMagnificationFrame.centerX();
|
||||
}
|
||||
if (Float.isNaN(centerX)) {
|
||||
centerY = mMagnificationFrame.centerY();
|
||||
}
|
||||
|
||||
final int frameWidth = width - 2 * mMirrorSurfaceMargin;
|
||||
final int frameHeight = height - 2 * mMirrorSurfaceMargin;
|
||||
setMagnificationFrame(frameWidth, frameHeight, (int) centerX, (int) centerY);
|
||||
calculateMagnificationFrameBoundary();
|
||||
// Correct the frame position to ensure it is inside the boundary.
|
||||
updateMagnificationFramePosition(0, 0);
|
||||
modifyWindowMagnification(true);
|
||||
}
|
||||
|
||||
private void setMagnificationFrame(int width, int height, int centerX, int centerY) {
|
||||
// Sets the initial frame area for the mirror and place it to the given center on the
|
||||
// display.
|
||||
final int initX = centerX - width / 2;
|
||||
final int initY = centerY - height / 2;
|
||||
mMagnificationFrame.set(initX, initY, initX + width, initY + height);
|
||||
}
|
||||
|
||||
private Size getDefaultWindowSizeWithWindowBounds(Rect windowBounds) {
|
||||
int initSize = Math.min(windowBounds.width(), windowBounds.height()) / 2;
|
||||
initSize = Math.min(mResources.getDimensionPixelSize(R.dimen.magnification_max_frame_size),
|
||||
initSize);
|
||||
initSize += 2 * mMirrorSurfaceMargin;
|
||||
final int initX = centerX - initSize / 2;
|
||||
final int initY = centerY - initSize / 2;
|
||||
mMagnificationFrame.set(initX, initY, initX + initSize, initY + initSize);
|
||||
return new Size(initSize, initSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,8 +637,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
}
|
||||
mTransaction.show(mMirrorSurface)
|
||||
.reparent(mMirrorSurface, mMirrorSurfaceView.getSurfaceControl());
|
||||
|
||||
modifyWindowMagnification(mTransaction);
|
||||
modifyWindowMagnification(false);
|
||||
}
|
||||
|
||||
private void addDragTouchListeners() {
|
||||
@@ -615,18 +655,25 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the placement of the mirrored content when the position of mMirrorView is updated.
|
||||
* Modifies the placement of the mirrored content when the position or size of mMirrorView is
|
||||
* updated.
|
||||
*
|
||||
* @param computeWindowSize set to {@code true} to compute window size with
|
||||
* {@link #mMagnificationFrame}.
|
||||
*/
|
||||
private void modifyWindowMagnification(SurfaceControl.Transaction t) {
|
||||
private void modifyWindowMagnification(boolean computeWindowSize) {
|
||||
mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback);
|
||||
updateMirrorViewLayout();
|
||||
updateMirrorViewLayout(computeWindowSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the layout params of MirrorView and translates MirrorView position when the view is
|
||||
* moved close to the screen edges.
|
||||
* Updates the layout params of MirrorView based on the size of {@link #mMagnificationFrame}
|
||||
* and translates MirrorView position when the view is moved close to the screen edges;
|
||||
*
|
||||
* @param computeWindowSize set to {@code true} to compute window size with
|
||||
* {@link #mMagnificationFrame}.
|
||||
*/
|
||||
private void updateMirrorViewLayout() {
|
||||
private void updateMirrorViewLayout(boolean computeWindowSize) {
|
||||
if (!isWindowVisible()) {
|
||||
return;
|
||||
}
|
||||
@@ -637,6 +684,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
(LayoutParams) mMirrorView.getLayoutParams();
|
||||
params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
|
||||
params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
|
||||
if (computeWindowSize) {
|
||||
params.width = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
|
||||
params.height = mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin;
|
||||
}
|
||||
|
||||
// Translates MirrorView position to make MirrorSurfaceView that is inside MirrorView
|
||||
// able to move close to the screen edges.
|
||||
@@ -899,7 +950,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
createMirrorWindow();
|
||||
showControls();
|
||||
} else {
|
||||
modifyWindowMagnification(mTransaction);
|
||||
modifyWindowMagnification(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +981,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
return;
|
||||
}
|
||||
if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) {
|
||||
modifyWindowMagnification(mTransaction);
|
||||
modifyWindowMagnification(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,9 +1065,15 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
|
||||
pw.println(" mOverlapWithGestureInsets:" + mOverlapWithGestureInsets);
|
||||
pw.println(" mScale:" + mScale);
|
||||
pw.println(" mMirrorViewBounds:" + (isWindowVisible() ? mMirrorViewBounds : "empty"));
|
||||
pw.println(" mMagnificationFrameBoundary:"
|
||||
+ (isWindowVisible() ? mMagnificationFrameBoundary : "empty"));
|
||||
pw.println(" mMagnificationFrame:"
|
||||
+ (isWindowVisible() ? mMagnificationFrame : "empty"));
|
||||
pw.println(" mSourceBounds:"
|
||||
+ (isWindowVisible() ? mSourceBounds : "empty"));
|
||||
pw.println(" mSystemGestureTop:" + mSystemGestureTop);
|
||||
pw.println(" mMagnificationFrameOffsetX:" + mMagnificationFrameOffsetX);
|
||||
pw.println(" mMagnificationFrameOffsetY:" + mMagnificationFrameOffsetY);
|
||||
}
|
||||
|
||||
private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate {
|
||||
|
||||
@@ -88,6 +88,7 @@ import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@LargeTest
|
||||
@TestableLooper.RunWithLooper
|
||||
@@ -345,15 +346,17 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void onOrientationChanged_disabled_updateDisplayRotation() {
|
||||
final Display display = Mockito.spy(mContext.getDisplay());
|
||||
when(display.getRotation()).thenReturn(Surface.ROTATION_90);
|
||||
when(mContext.getDisplay()).thenReturn(display);
|
||||
final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
|
||||
// Rotate the window clockwise 90 degree.
|
||||
windowBounds.set(windowBounds.top, windowBounds.left, windowBounds.bottom,
|
||||
windowBounds.right);
|
||||
mWindowManager.setWindowBounds(windowBounds);
|
||||
final int newRotation = simulateRotateTheDevice();
|
||||
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION);
|
||||
});
|
||||
mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.onConfigurationChanged(
|
||||
ActivityInfo.CONFIG_ORIENTATION));
|
||||
|
||||
assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation);
|
||||
assertEquals(newRotation, mWindowMagnificationController.mRotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -603,6 +606,113 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
ReferenceTestUtils.waitForCondition(() -> hasMagnificationOverlapFlag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMinimumWindowSize_enabled_expectedWindowSize() {
|
||||
final int minimumWindowSize = mResources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
|
||||
final int expectedWindowHeight = minimumWindowSize;
|
||||
final int expectedWindowWidth = minimumWindowSize;
|
||||
mInstrumentation.runOnMainSync(
|
||||
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
|
||||
Float.NaN, Float.NaN));
|
||||
|
||||
final AtomicInteger actualWindowHeight = new AtomicInteger();
|
||||
final AtomicInteger actualWindowWidth = new AtomicInteger();
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight);
|
||||
actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
|
||||
actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
|
||||
|
||||
});
|
||||
|
||||
assertEquals(expectedWindowHeight, actualWindowHeight.get());
|
||||
assertEquals(expectedWindowWidth, actualWindowWidth.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMinimumWindowSizeThenEnable_expectedWindowSize() {
|
||||
final int minimumWindowSize = mResources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
|
||||
final int expectedWindowHeight = minimumWindowSize;
|
||||
final int expectedWindowWidth = minimumWindowSize;
|
||||
|
||||
final AtomicInteger actualWindowHeight = new AtomicInteger();
|
||||
final AtomicInteger actualWindowWidth = new AtomicInteger();
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.setWindowSize(expectedWindowWidth, expectedWindowHeight);
|
||||
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
|
||||
Float.NaN, Float.NaN);
|
||||
actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
|
||||
actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
|
||||
});
|
||||
|
||||
assertEquals(expectedWindowHeight, actualWindowHeight.get());
|
||||
assertEquals(expectedWindowWidth, actualWindowWidth.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWindowSizeLessThanMin_enabled_minimumWindowSize() {
|
||||
final int minimumWindowSize = mResources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
|
||||
mInstrumentation.runOnMainSync(
|
||||
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
|
||||
Float.NaN, Float.NaN));
|
||||
|
||||
final AtomicInteger actualWindowHeight = new AtomicInteger();
|
||||
final AtomicInteger actualWindowWidth = new AtomicInteger();
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.setWindowSize(minimumWindowSize - 10,
|
||||
minimumWindowSize - 10);
|
||||
actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
|
||||
actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
|
||||
});
|
||||
|
||||
assertEquals(minimumWindowSize, actualWindowHeight.get());
|
||||
assertEquals(minimumWindowSize, actualWindowWidth.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWindowSizeLargerThanScreenSize_enabled_windowSizeIsScreenSize() {
|
||||
final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
|
||||
mInstrumentation.runOnMainSync(
|
||||
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
|
||||
Float.NaN, Float.NaN));
|
||||
|
||||
final AtomicInteger actualWindowHeight = new AtomicInteger();
|
||||
final AtomicInteger actualWindowWidth = new AtomicInteger();
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.setWindowSize(bounds.width() + 10, bounds.height() + 10);
|
||||
actualWindowHeight.set(mWindowManager.getLayoutParamsFromAttachedView().height);
|
||||
actualWindowWidth.set(mWindowManager.getLayoutParamsFromAttachedView().width);
|
||||
});
|
||||
|
||||
assertEquals(bounds.height(), actualWindowHeight.get());
|
||||
assertEquals(bounds.width(), actualWindowWidth.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setWindowCenterOutOfScreen_enabled_magnificationCenterIsInsideTheScreen() {
|
||||
|
||||
final int minimumWindowSize = mResources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
|
||||
final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
|
||||
mInstrumentation.runOnMainSync(
|
||||
() -> mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
|
||||
Float.NaN, Float.NaN));
|
||||
|
||||
final AtomicInteger magnificationCenterX = new AtomicInteger();
|
||||
final AtomicInteger magnificationCenterY = new AtomicInteger();
|
||||
mInstrumentation.runOnMainSync(() -> {
|
||||
mWindowMagnificationController.setWindowSizeAndCenter(minimumWindowSize,
|
||||
minimumWindowSize, bounds.right, bounds.bottom);
|
||||
magnificationCenterX.set((int) mWindowMagnificationController.getCenterX());
|
||||
magnificationCenterY.set((int) mWindowMagnificationController.getCenterY());
|
||||
});
|
||||
|
||||
assertTrue(magnificationCenterX.get() < bounds.right);
|
||||
assertTrue(magnificationCenterY.get() < bounds.bottom);
|
||||
}
|
||||
|
||||
private CharSequence getAccessibilityWindowTitle() {
|
||||
final View mirrorView = mWindowManager.getAttachedView();
|
||||
if (mirrorView == null) {
|
||||
|
||||
Reference in New Issue
Block a user