Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96e0ef37 authored by Candice Lo's avatar Candice Lo Committed by Android (Google) Code Review
Browse files

Merge changes Id35c2ff3,I37762e00 into main

* changes:
  Keeping the magnifier window size in SharedPreference
  Match default magnifier window size to Medium in settings
parents f56bebdb b4a82ddb
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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>
+36 −15
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+71 −0
Original line number Diff line number Diff line
/*
 * 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));
    }

}
+50 −15
Original line number Diff line number Diff line
@@ -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 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_windowSizeIsConstrained() {
    public void screenSizeIsChangedToLarge_enabled_defaultWindowSize() {
        mInstrumentation.runOnMainSync(() -> {
            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                    Float.NaN);
        });
        final int screenSize = mContext.getResources().getDimensionPixelSize(
                R.dimen.magnification_max_frame_size) * 10;
        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());
+56 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}