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(); + } +}