Merge changes Id35c2ff3,I37762e00 into main

* changes:
  Keeping the magnifier window size in SharedPreference
  Match default magnifier window size to Medium in settings
This commit is contained in:
Candice Lo
2023-08-02 02:11:42 +00:00
committed by Android (Google) Code Review
5 changed files with 213 additions and 31 deletions

View File

@@ -1196,7 +1196,6 @@
<dimen name="magnification_window_drag_corner_stroke">3dp</dimen>
<!-- The extra padding to show the whole outer border -->
<dimen name="magnifier_drag_handle_padding">3dp</dimen>
<dimen name="magnification_max_frame_size">300dp</dimen>
<!-- Magnification settings panel -->
<dimen name="magnification_setting_view_margin">24dp</dimen>
<dimen name="magnification_setting_text_size">18sp</dimen>

View File

@@ -124,7 +124,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private float mScale;
/**
* MagnificationFrame represents the bound of {@link #mMirrorSurface} and is constrained
* MagnificationFrame represents the bound of {@link #mMirrorSurfaceView} and is constrained
* by the {@link #mMagnificationFrameBoundary}.
* We use MagnificationFrame to calculate the position of {@link #mMirrorView}.
* We combine MagnificationFrame with {@link #mMagnificationFrameOffsetX} and
@@ -225,6 +225,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private boolean mAllowDiagonalScrolling = false;
private boolean mEditSizeEnable = false;
private boolean mSettingsPanelVisibility = false;
@VisibleForTesting
WindowMagnificationSizePrefs mWindowMagnificationSizePrefs;
@Nullable
private final MirrorWindowControl mMirrorWindowControl;
@@ -249,6 +251,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mWindowMagnifierCallback = callback;
mSysUiState = sysUiState;
mConfiguration = new Configuration(context.getResources().getConfiguration());
mWindowMagnificationSizePrefs = new WindowMagnificationSizePrefs(mContext);
final Display display = mContext.getDisplay();
mDisplayId = mContext.getDisplayId();
@@ -272,8 +275,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
com.android.internal.R.integer.config_shortAnimTime);
updateDimensions();
final Size windowSize = getDefaultWindowSizeWithWindowBounds(mWindowBounds);
setMagnificationFrame(windowSize.getWidth(), windowSize.getHeight(),
final Size windowFrameSize = restoreMagnificationWindowFrameSizeIfPossible();
setMagnificationFrame(windowFrameSize.getWidth(), windowFrameSize.getHeight(),
mWindowBounds.width() / 2, mWindowBounds.height() / 2);
computeBounceAnimationScale();
@@ -381,12 +384,16 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
if (!mMagnificationSizeScaleOptions.contains(index)) {
return;
}
final float scale = mMagnificationSizeScaleOptions.get(index, 1.0f);
final int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3;
int size = (int) (initSize * scale);
int size = getMagnificationWindowSizeFromIndex(index);
setWindowSize(size, size);
}
int getMagnificationWindowSizeFromIndex(@MagnificationSize int index) {
final float scale = mMagnificationSizeScaleOptions.get(index, 1.0f);
int initSize = Math.min(mWindowBounds.width(), mWindowBounds.height()) / 3;
return (int) (initSize * scale) - (int) (initSize * scale) % 2;
}
void setEditMagnifierSizeMode(boolean enable) {
mEditSizeEnable = enable;
applyResourcesValues();
@@ -395,6 +402,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
updateDimensions();
applyTapExcludeRegion();
}
if (!enable) {
// Keep the magnifier size when exiting edit mode
mWindowMagnificationSizePrefs.saveSizeForCurrentDensity(
new Size(mMagnificationFrame.width(), mMagnificationFrame.height()));
}
}
void setDiagonalScrolling(boolean enable) {
@@ -519,12 +532,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
return false;
}
mWindowBounds.set(currentWindowBounds);
final Size windowSize = getDefaultWindowSizeWithWindowBounds(mWindowBounds);
final Size windowFrameSize = restoreMagnificationWindowFrameSizeIfPossible();
final float newCenterX = (getCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
final float newCenterY = (getCenterY()) * mWindowBounds.height() / oldWindowBounds.height();
setMagnificationFrame(windowSize.getWidth(), windowSize.getHeight(), (int) newCenterX,
(int) newCenterY);
setMagnificationFrame(windowFrameSize.getWidth(), windowFrameSize.getHeight(),
(int) newCenterX, (int) newCenterY);
calculateMagnificationFrameBoundary();
return true;
}
@@ -738,6 +751,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
}
private void setMagnificationFrame(int width, int height, int centerX, int centerY) {
mWindowMagnificationSizePrefs.saveSizeForCurrentDensity(new Size(width, height));
// Sets the initial frame area for the mirror and place it to the given center on the
// display.
final int initX = centerX - width / 2;
@@ -745,12 +760,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
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;
return new Size(initSize, initSize);
private Size restoreMagnificationWindowFrameSizeIfPossible() {
if (!mWindowMagnificationSizePrefs.isPreferenceSavedForCurrentDensity()) {
return getDefaultMagnificationWindowFrameSize();
}
return mWindowMagnificationSizePrefs.getSizeForCurrentDensity();
}
private Size getDefaultMagnificationWindowFrameSize() {
final int defaultSize = getMagnificationWindowSizeFromIndex(MagnificationSize.MEDIUM)
- 2 * mMirrorSurfaceMargin;
return new Size(defaultSize, defaultSize);
}
/**

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.accessibility;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Size;
/**
* Class to handle SharedPreference for window magnification size.
*/
public final class WindowMagnificationSizePrefs {
private static final String WINDOW_MAGNIFICATION_PREFERENCES =
"window_magnification_preferences";
Context mContext;
SharedPreferences mWindowMagnificationSizePreferences;
public WindowMagnificationSizePrefs(Context context) {
mContext = context;
mWindowMagnificationSizePreferences = mContext
.getSharedPreferences(WINDOW_MAGNIFICATION_PREFERENCES, Context.MODE_PRIVATE);
}
/**
* Uses smallest screen width DP as the key for preference.
*/
private String getKey() {
return String.valueOf(
mContext.getResources().getConfiguration().smallestScreenWidthDp);
}
/**
* Saves the window frame size for current screen density.
*/
public void saveSizeForCurrentDensity(Size size) {
mWindowMagnificationSizePreferences.edit()
.putString(getKey(), size.toString()).apply();
}
/**
* Check if there is a preference saved for current screen density.
*
* @return true if there is a preference saved for current screen density, false if it is unset.
*/
public boolean isPreferenceSavedForCurrentDensity() {
return mWindowMagnificationSizePreferences.contains(getKey());
}
/**
* Gets the size preference for current screen density.
*/
public Size getSizeForCurrentDensity() {
return Size.parseSize(mWindowMagnificationSizePreferences.getString(getKey(), null));
}
}

View File

@@ -71,6 +71,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableResources;
import android.text.TextUtils;
import android.util.Size;
import android.view.Display;
import android.view.IWindowSession;
import android.view.MotionEvent;
@@ -100,6 +101,7 @@ import com.google.common.util.concurrent.AtomicDouble;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -313,10 +315,10 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
assertFalse(rects.isEmpty());
}
@Ignore("The default window size should be constrained after fixing b/288056772")
@Test
public void enableWindowMagnification_LargeScreen_windowSizeIsConstrained() {
final int screenSize = mContext.getResources().getDimensionPixelSize(
R.dimen.magnification_max_frame_size) * 10;
final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10;
mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
mInstrumentation.runOnMainSync(() -> {
@@ -543,17 +545,22 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
}
@Test
public void onScreenSizeChanged_enabledAtTheCenterOfScreen_keepSameWindowSizeRatio() {
public void onScreenSizeAndDensityChanged_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.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
// Screen size and density change
mContext.getResources().getConfiguration().smallestScreenWidthDp =
mContext.getResources().getConfiguration().smallestScreenWidthDp * 2;
final Rect testWindowBounds = new Rect(
mWindowManager.getCurrentWindowMetrics().getBounds());
testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
testWindowBounds.right + 100, testWindowBounds.bottom + 100);
mWindowManager.setWindowBounds(testWindowBounds);
mInstrumentation.runOnMainSync(() -> {
@@ -568,26 +575,49 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
mWindowMagnificationController.getCenterY() / testWindowBounds.height(),
0);
}
@Test
public void screenSizeIsChangedToLarge_enabled_windowSizeIsConstrained() {
public void onScreenChangedToSavedDensity_enabled_restoreSavedMagnifierWindow() {
mContext.getResources().getConfiguration().smallestScreenWidthDp =
mContext.getResources().getConfiguration().smallestScreenWidthDp * 2;
int windowFrameSize = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.accessibility_window_magnifier_min_size);
mWindowMagnificationController.mWindowMagnificationSizePrefs.saveSizeForCurrentDensity(
new Size(windowFrameSize, windowFrameSize));
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
final int screenSize = mContext.getResources().getDimensionPixelSize(
R.dimen.magnification_max_frame_size) * 10;
WindowManager.LayoutParams params = mWindowManager.getLayoutParamsFromAttachedView();
assertTrue(params.width == windowFrameSize);
assertTrue(params.height == windowFrameSize);
}
@Test
public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
Float.NaN);
});
final int screenSize = mWindowManager.getCurrentWindowMetrics().getBounds().width() * 10;
// Screen size and density change
mContext.getResources().getConfiguration().smallestScreenWidthDp =
mContext.getResources().getConfiguration().smallestScreenWidthDp * 2;
mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_SCREEN_SIZE);
});
final int halfScreenSize = screenSize / 2;
final int defaultWindowSize =
mWindowMagnificationController.getMagnificationWindowSizeFromIndex(
WindowMagnificationSettings.MagnificationSize.MEDIUM);
WindowManager.LayoutParams params = mWindowManager.getLayoutParamsFromAttachedView();
// The frame size should be the half of smaller value of window height/width unless it
//exceed the max frame size.
assertTrue(params.width < halfScreenSize);
assertTrue(params.height < halfScreenSize);
assertTrue(params.width == defaultWindowSize);
assertTrue(params.height == defaultWindowSize);
}
@Test
@@ -1136,6 +1166,11 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
mWindowManager.setWindowInsets(testInsets);
}
private int updateMirrorSurfaceMarginDimension() {
return mContext.getResources().getDimensionPixelSize(
R.dimen.magnification_mirror_surface_margin);
}
@Surface.Rotation
private int simulateRotateTheDevice() {
final Display display = Mockito.spy(mContext.getDisplay());

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.accessibility;
import static com.google.common.truth.Truth.assertThat;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Size;
import com.android.systemui.SysuiTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class WindowMagnificationSizePrefsTest extends SysuiTestCase {
WindowMagnificationSizePrefs mWindowMagnificationSizePrefs =
new WindowMagnificationSizePrefs(mContext);
@Test
public void saveSizeForCurrentDensity_getExpectedSize() {
Size testSize = new Size(500, 500);
mWindowMagnificationSizePrefs.saveSizeForCurrentDensity(testSize);
assertThat(mWindowMagnificationSizePrefs.getSizeForCurrentDensity())
.isEqualTo(testSize);
}
@Test
public void saveSizeForCurrentDensity_containsPreferenceForCurrentDensity() {
Size testSize = new Size(500, 500);
mWindowMagnificationSizePrefs.saveSizeForCurrentDensity(testSize);
assertThat(mWindowMagnificationSizePrefs.isPreferenceSavedForCurrentDensity())
.isTrue();
}
}