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

Commit dc1335dc authored by Candice's avatar Candice
Browse files

fix(fullscreen magnification): Fix action in configuration changes

1. Save the activation status information and guard the activation check
   in onFullscreenMagnificationActivationChanged
2. When there is a configuration change on CONFIG_DENSITY/
   CONFIG_SCREEN_SIZE/CONFIG_ORIENTATION: (1) update the dimension of the
   resources and the current window bounds (2) update the border view
   layout parameters accordingly.

Bug: 291891390
Bug: 334888523
Test: atest FullscreenMagnificationControllerTest
      atest AccessibilityMagnificationTest
Flag: ACONFIG always_draw_magnification_fullscreen_border STAGING
Change-Id: I723b58a0111fa3db608d99e5f1c52e5c942b34d6
parent 013f1644
Loading
Loading
Loading
Loading
+58 −10
Original line number Diff line number Diff line
@@ -23,7 +23,10 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.UiContext;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
@@ -47,7 +50,7 @@ import com.android.systemui.res.R;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

class FullscreenMagnificationController {
class FullscreenMagnificationController implements ComponentCallbacks {

    private final Context mContext;
    private final AccessibilityManager mAccessibilityManager;
@@ -63,6 +66,8 @@ class FullscreenMagnificationController {
    private static final Region sEmptyRegion = new Region();
    private ValueAnimator mShowHideBorderAnimator;
    private Executor mExecutor;
    private boolean mFullscreenMagnificationActivated = false;
    private final Configuration mConfiguration;

    FullscreenMagnificationController(
            @UiContext Context context,
@@ -95,6 +100,7 @@ class FullscreenMagnificationController {
                - mContext.getResources().getDimensionPixelSize(
                R.dimen.magnifier_border_width_fullscreen);
        mDisplayId = mContext.getDisplayId();
        mConfiguration = new Configuration(context.getResources().getConfiguration());
        mShowHideBorderAnimator = valueAnimator;
        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
@@ -121,20 +127,21 @@ class FullscreenMagnificationController {
    }

    /**
     * In {@link com.android.server.accessibility.magnification.FullScreenMagnificationController
     * .DisplayMagnification#setActivated(boolean)}, onFullScreenMagnificationActivationState is
     * only called when there is an activation status change. Therefore, we could assume that we
     * won't be calling "create border" when another creating border animation is running or
     * "remove border" when another removing border animation is running.
     * Check the fullscreen magnification activation status, and proceed corresponding actions when
     * there is an activation change.
     */
    @UiThread
    void onFullscreenMagnificationActivationChanged(boolean activated) {
        final boolean changed = (mFullscreenMagnificationActivated != activated);
        if (changed) {
            mFullscreenMagnificationActivated = activated;
            if (activated) {
                createFullscreenMagnificationBorder();
            } else {
                removeFullscreenMagnificationBorder();
            }
        }
    }

    /**
     * This method should only be called when fullscreen magnification is changed from activated
@@ -142,6 +149,7 @@ class FullscreenMagnificationController {
     */
    @UiThread
    private void removeFullscreenMagnificationBorder() {
        mContext.unregisterComponentCallbacks(this);
        mShowHideBorderAnimator.reverse();
    }

@@ -162,6 +170,9 @@ class FullscreenMagnificationController {
     */
    @UiThread
    private void createFullscreenMagnificationBorder() {
        onConfigurationChanged(mContext.getResources().getConfiguration());
        mContext.registerComponentCallbacks(this);

        if (mSurfaceControlViewHost == null) {
            // Create the view only if it does not exist yet. If we are trying to enable fullscreen
            // magnification before it was fully disabled, we use the previous view instead of
@@ -226,4 +237,41 @@ class FullscreenMagnificationController {
        // all touch events to go through this view.
        surfaceControl.setTouchableRegion(sEmptyRegion);
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        final int configDiff = newConfig.diff(mConfiguration);
        mConfiguration.setTo(newConfig);
        onConfigurationChanged(configDiff);
    }

    @VisibleForTesting
    void onConfigurationChanged(int configDiff) {
        boolean reCreateWindow = false;
        if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0
                || (configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
                || (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
            updateDimensions();
            mWindowBounds.set(mWindowManager.getCurrentWindowMetrics().getBounds());
            reCreateWindow = true;
        }

        if (mFullscreenBorder != null && reCreateWindow) {
            final int newWidth = mWindowBounds.width() + 2 * mBorderOffset;
            final int newHeight = mWindowBounds.height() + 2 * mBorderOffset;
            mSurfaceControlViewHost.relayout(newWidth, newHeight);
        }
    }

    private void updateDimensions() {
        mBorderOffset = mContext.getResources().getDimensionPixelSize(
                R.dimen.magnifier_border_width_fullscreen_with_offset)
                - mContext.getResources().getDimensionPixelSize(
                        R.dimen.magnifier_border_width_fullscreen);
    }

    @Override
    public void onLowMemory() {

    }
}
+48 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;
@@ -46,6 +49,7 @@ import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.res.R;

import org.junit.After;
import org.junit.Before;
@@ -68,6 +72,7 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase {
    private SurfaceControlViewHost mSurfaceControlViewHost;
    private ValueAnimator mShowHideBorderAnimator;
    private SurfaceControl.Transaction mTransaction;
    private TestableWindowManager mWindowManager;

    @Before
    public void setUp() {
@@ -75,6 +80,9 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase {
                spy(new SurfaceControlViewHost(mContext, mContext.getDisplay(),
                        new InputTransferToken(), "FullscreenMagnification")));
        Supplier<SurfaceControlViewHost> scvhSupplier = () -> mSurfaceControlViewHost;
        final WindowManager wm = mContext.getSystemService(WindowManager.class);
        mWindowManager = new TestableWindowManager(wm);
        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);

        mTransaction = new SurfaceControl.Transaction();
        mShowHideBorderAnimator = spy(newNullTargetObjectAnimator());
@@ -187,6 +195,46 @@ public class FullscreenMagnificationControllerTest extends SysuiTestCase {
        verify(mShowHideBorderAnimator).reverse();
    }

    @Test
    public void onScreenSizeChanged_activated_borderChangedToExpectedSize()
            throws InterruptedException {
        CountDownLatch transactionCommittedLatch = new CountDownLatch(1);
        CountDownLatch animationEndLatch = new CountDownLatch(1);
        mTransaction.addTransactionCommittedListener(
                Runnable::run, transactionCommittedLatch::countDown);
        mShowHideBorderAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                animationEndLatch.countDown();
            }
        });
        getInstrumentation().runOnMainSync(() ->
                //Enable fullscreen magnification
                mFullscreenMagnificationController
                        .onFullscreenMagnificationActivationChanged(true));
        assertTrue("Failed to wait for transaction committed",
                transactionCommittedLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
        assertTrue("Failed to wait for animation to be finished",
                animationEndLatch.await(ANIMATION_TIMEOUT_MS, TimeUnit.MILLISECONDS));
        final Rect testWindowBounds = new Rect(
                mWindowManager.getCurrentWindowMetrics().getBounds());
        testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
                testWindowBounds.right + 100, testWindowBounds.bottom + 100);
        mWindowManager.setWindowBounds(testWindowBounds);

        getInstrumentation().runOnMainSync(() ->
                mFullscreenMagnificationController.onConfigurationChanged(
                        ActivityInfo.CONFIG_SCREEN_SIZE));

        int borderOffset = mContext.getResources().getDimensionPixelSize(
                R.dimen.magnifier_border_width_fullscreen_with_offset)
                - mContext.getResources().getDimensionPixelSize(
                R.dimen.magnifier_border_width_fullscreen);
        final int newWidth = testWindowBounds.width() + 2 * borderOffset;
        final int newHeight = testWindowBounds.height() + 2 * borderOffset;
        verify(mSurfaceControlViewHost).relayout(newWidth, newHeight);
    }

    private ValueAnimator newNullTargetObjectAnimator() {
        final ValueAnimator animator =
                ObjectAnimator.ofFloat(/* target= */ null, View.ALPHA, 0f, 1f);