Keeping the magnifier window size in SharedPreference

Using the smallest width dp as the key to save magnifier window's width and height. If no corresponding saved window size is found, use the Medium size provided by the settings panel button to be the default magnifier size.

Bug: 265363901
Bug: 283019152
Test: atest WindowMagnificationControllerTest
Test: atest WindowMagnificationSizePrefsTest
Test: manually - test window size is restored after the device restarts
Change-Id: Id35c2ff394c9a4907240833f3d43b0d412ef6caf
This commit is contained in:
Candice Lo
2023-07-13 07:00:26 +00:00
parent 3c79503330
commit b4a82ddb2d
4 changed files with 186 additions and 7 deletions

View File

@@ -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,7 +275,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
com.android.internal.R.integer.config_shortAnimTime);
updateDimensions();
final Size windowFrameSize = getDefaultMagnificationWindowFrameSize();
final Size windowFrameSize = restoreMagnificationWindowFrameSizeIfPossible();
setMagnificationFrame(windowFrameSize.getWidth(), windowFrameSize.getHeight(),
mWindowBounds.width() / 2, mWindowBounds.height() / 2);
computeBounceAnimationScale();
@@ -399,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) {
@@ -523,7 +532,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
return false;
}
mWindowBounds.set(currentWindowBounds);
final Size windowFrameSize = getDefaultMagnificationWindowFrameSize();
final Size windowFrameSize = restoreMagnificationWindowFrameSizeIfPossible();
final float newCenterX = (getCenterX()) * mWindowBounds.width() / oldWindowBounds.width();
final float newCenterY = (getCenterY()) * mWindowBounds.height() / oldWindowBounds.height();
@@ -742,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;
@@ -749,6 +760,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mMagnificationFrame.set(initX, initY, initX + width, initY + height);
}
private Size restoreMagnificationWindowFrameSizeIfPossible() {
if (!mWindowMagnificationSizePrefs.isPreferenceSavedForCurrentDensity()) {
return getDefaultMagnificationWindowFrameSize();
}
return mWindowMagnificationSizePrefs.getSizeForCurrentDensity();
}
private Size getDefaultMagnificationWindowFrameSize() {
final int defaultSize = getMagnificationWindowSizeFromIndex(MagnificationSize.MEDIUM)
- 2 * mMirrorSurfaceMargin;

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;
@@ -544,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(() -> {
@@ -570,6 +576,25 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
0);
}
@Test
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);
});
WindowManager.LayoutParams params = mWindowManager.getLayoutParamsFromAttachedView();
assertTrue(params.width == windowFrameSize);
assertTrue(params.height == windowFrameSize);
}
@Test
public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() {
mInstrumentation.runOnMainSync(() -> {
@@ -577,6 +602,9 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
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(() -> {
@@ -1138,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();
}
}