From b4a82ddb2df47c80f9632c3bc1b79013131dec0d Mon Sep 17 00:00:00 2001 From: Candice Lo Date: Thu, 13 Jul 2023 07:00:26 +0000 Subject: [PATCH] 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 --- .../WindowMagnificationController.java | 23 +++++- .../WindowMagnificationSizePrefs.java | 71 +++++++++++++++++++ .../WindowMagnificationControllerTest.java | 43 +++++++++-- .../WindowMagnificationSizePrefsTest.java | 56 +++++++++++++++ 4 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSizePrefs.java create mode 100644 packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index 197aa90723cb1..4a31f3d9cf908 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSizePrefs.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSizePrefs.java new file mode 100644 index 0000000000000..4d7ad2647c1f4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSizePrefs.java @@ -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)); + } + +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 670ed400681b6..f1615c86d7892 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -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()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java new file mode 100644 index 0000000000000..04b0d70851157 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationSizePrefsTest.java @@ -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(); + } +}