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

Commit 249b619b authored by Ryan Lin's avatar Ryan Lin Committed by Android (Google) Code Review
Browse files

Merge "Support individual magnification mode for each display"

parents a3b8b6d6 b68bbe05
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
import android.view.Gravity;
@@ -75,6 +74,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
    private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
    private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
    private final LayoutParams mParams;
    private final SwitchListener mSwitchListener;
    @VisibleForTesting
    final Rect mDraggableWindowBounds = new Rect();
    private boolean mIsVisible = false;
@@ -82,17 +82,29 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
    private boolean mSingleTapDetected = false;
    private boolean mToLeftScreenEdge = false;

    MagnificationModeSwitch(@UiContext Context context) {
        this(context, createView(context), new SfVsyncFrameCallbackProvider());
    public interface SwitchListener {
        /**
         * Called when the switch is clicked to change the magnification mode.
         * @param displayId the display id of the display to which the view's window has been
         *                  attached
         * @param magnificationMode the magnification mode
         */
        void onSwitch(int displayId, int magnificationMode);
    }

    MagnificationModeSwitch(@UiContext Context context,
            SwitchListener switchListener) {
        this(context, createView(context), new SfVsyncFrameCallbackProvider(), switchListener);
    }

    @VisibleForTesting
    MagnificationModeSwitch(Context context, @NonNull ImageView imageView,
            SfVsyncFrameCallbackProvider sfVsyncFrameProvider) {
            SfVsyncFrameCallbackProvider sfVsyncFrameProvider, SwitchListener switchListener) {
        mContext = context;
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
        mWindowManager = mContext.getSystemService(WindowManager.class);
        mSfVsyncFrameProvider = sfVsyncFrameProvider;
        mSwitchListener = switchListener;
        mParams = createLayoutParams(context);
        mImageView = imageView;
        mImageView.setOnTouchListener(this::onTouch);
@@ -364,11 +376,7 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
                mMagnificationMode ^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
        mMagnificationMode = newMode;
        mImageView.setImageResource(getIconResId(newMode));
        Settings.Secure.putIntForUser(
                mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
                newMode,
                UserHandle.USER_CURRENT);
        mSwitchListener.onSwitch(mContext.getDisplayId(), newMode);
    }

    private void handleSingleTap() {
+29 −7
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.accessibility;

import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;

import static com.android.systemui.accessibility.MagnificationModeSwitch.SwitchListener;

import android.annotation.MainThread;
import android.content.Context;
import android.hardware.display.DisplayManager;
@@ -27,21 +29,24 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;

/**
 * A class to control {@link MagnificationModeSwitch}. It should show the button UI with following
 * A class to control {@link MagnificationModeSwitch}. It shows the button UI with following
 * conditions:
 * <ol>
 *   <li> Both full-screen and window magnification mode are capable.</li>
 *   <li> The magnification scale is changed by a user.</li>
 * <ol>
 * The switch action will be handled by {@link #mSwitchListenerDelegate} which informs the system
 * server about the changed mode.
 */
@SysUISingleton
public class ModeSwitchesController {
public class ModeSwitchesController implements SwitchListener {

    private final DisplayIdIndexSupplier<MagnificationModeSwitch> mSwitchSupplier;
    private SwitchListener mSwitchListenerDelegate;

    public ModeSwitchesController(Context context) {
        mSwitchSupplier = new SwitchSupplier(context,
                context.getSystemService(DisplayManager.class));
                context.getSystemService(DisplayManager.class), this::onSwitch);
    }

    @VisibleForTesting
@@ -50,8 +55,8 @@ public class ModeSwitchesController {
    }

    /**
     * Shows a button that a user can click the button to switch magnification mode. And the
     * button would be dismissed automatically after the button is displayed for a period of time.
     * Shows a button that a user can click to switch magnification mode. And the button
     * would be dismissed automatically after the button is displayed for a period of time.
     *
     * @param displayId The logical display id
     * @param mode      The magnification mode
@@ -93,24 +98,41 @@ public class ModeSwitchesController {
                switchController -> switchController.onConfigurationChanged(configDiff));
    }

    @Override
    public void onSwitch(int displayId, int magnificationMode) {
        if (mSwitchListenerDelegate != null) {
            mSwitchListenerDelegate.onSwitch(displayId, magnificationMode);
        }
    }

    public void setSwitchListenerDelegate(SwitchListener switchListenerDelegate) {
        mSwitchListenerDelegate = switchListenerDelegate;
    }

    private static class SwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> {

        private final Context mContext;
        private final SwitchListener mSwitchListener;

        /**
         * Supplies the switch for the given display.
         *
         * @param context        Context
         * @param displayManager DisplayManager
         * @param switchListener The callback that will run when the switch is clicked
         */
        SwitchSupplier(Context context, DisplayManager displayManager) {
        SwitchSupplier(Context context, DisplayManager displayManager,
                SwitchListener switchListener) {
            super(displayManager);
            mContext = context;
            mSwitchListener = switchListener;
        }

        @Override
        protected MagnificationModeSwitch createInstance(Display display) {
            final Context uiContext = mContext.createWindowContext(display,
                    TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null);
            return new MagnificationModeSwitch(uiContext);
            return new MagnificationModeSwitch(uiContext, mSwitchListener);
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -243,12 +243,15 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
            mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this,
                    mHandler, mModeSwitchesController);
        }
        mModeSwitchesController.setSwitchListenerDelegate(
                mWindowMagnificationConnectionImpl::onChangeMagnificationMode);
        mAccessibilityManager.setWindowMagnificationConnection(
                mWindowMagnificationConnectionImpl);
    }

    private void clearWindowMagnificationConnection() {
        mAccessibilityManager.setWindowMagnificationConnection(null);
        mModeSwitchesController.setSwitchListenerDelegate(null);
        //TODO: destroy controllers.
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -130,4 +130,14 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S
            }
        }
    }

    void onChangeMagnificationMode(int displayId, int mode) {
        if (mConnectionCallback != null) {
            try {
                mConnectionCallback.onChangeMagnificationMode(displayId, mode);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to inform changing magnification mode", e);
            }
        }
    }
}
+28 −19
Original line number Diff line number Diff line
@@ -55,10 +55,9 @@ import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.SparseIntArray;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
@@ -101,6 +100,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    private AccessibilityManager mAccessibilityManager;
    @Mock
    private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
    private SwitchListenerStub mSwitchListener;
    private TestableWindowManager mWindowManager;
    private ViewPropertyAnimator mViewPropertyAnimator;
    private MagnificationModeSwitch mMagnificationModeSwitch;
@@ -112,6 +112,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        final WindowManager wm = mContext.getSystemService(WindowManager.class);
        mSwitchListener = new SwitchListenerStub();
        mWindowManager = spy(new TestableWindowManager(wm));
        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
        mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
@@ -130,7 +131,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        }).when(mSfVsyncFrameProvider).postFrameCallback(
                any(Choreographer.FrameCallback.class));
        mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView,
                mSfVsyncFrameProvider);
                mSfVsyncFrameProvider, mSwitchListener);
        assertNotNull(mTouchListener);
    }

@@ -326,8 +327,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    public void performDragging_showMagnificationButton_updateViewLayout() {
        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
        resetAndStubMockImageViewAndAnimator();
        final int previousMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);

        // Perform dragging
        final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
@@ -345,7 +344,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
                downTime, downTime, ACTION_UP, 100 + offset, 100));

        assertModeUnchanged(previousMode);
        assertModeUnchanged();
        assertShowFadingAnimation(FADE_OUT_ALPHA);
    }

@@ -353,8 +352,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    public void performSingleTapActionCanceled_showButtonAnimation() {
        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
        resetAndStubMockImageViewAndAnimator();
        final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);

        final long downTime = SystemClock.uptimeMillis();
        mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
@@ -363,7 +360,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
                downTime, downTime, ACTION_CANCEL, 100, 100));

        assertModeUnchanged(previousMode);
        assertModeUnchanged();
        assertShowFadingAnimation(FADE_OUT_ALPHA);
    }

@@ -371,8 +368,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    public void performDraggingActionCanceled_showButtonAnimation() {
        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
        resetAndStubMockImageViewAndAnimator();
        final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);

        // Perform dragging
        final long downTime = SystemClock.uptimeMillis();
@@ -385,7 +380,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
                downTime, downTime, ACTION_CANCEL, 100 + offset, 100));

        assertModeUnchanged(previousMode);
        assertModeUnchanged();
        assertShowFadingAnimation(FADE_OUT_ALPHA);
    }

@@ -529,10 +524,9 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        assertEquals(expectedY, mWindowManager.getLayoutParamsFromAttachedView().y);
    }

    private void assertModeUnchanged(int expectedMode) {
        final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
        assertEquals(expectedMode, actualMode);
    private void assertModeUnchanged() {
        assertEquals(SwitchListenerStub.MODE_INVALID,
                mSwitchListener.getChangedMode(mContext.getDisplayId()));
    }

    private void assertShowFadingAnimation(float alpha) {
@@ -594,9 +588,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        verify(mSpyImageView).setImageResource(
                getIconResId(expectedMode));
        verify(mWindowManager).removeView(mSpyImageView);
        final int actualMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);
        assertEquals(expectedMode, actualMode);
        final int changedMode = mSwitchListener.getChangedMode(mContext.getDisplayId());
        assertEquals(expectedMode, changedMode);
    }

    private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action, float x,
@@ -621,4 +614,20 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        assertEquals(expectedX, layoutParams.x);
        assertEquals(expectedY, layoutParams.y);
    }

    private static class SwitchListenerStub implements MagnificationModeSwitch.SwitchListener {

        private static final int MODE_INVALID = -1;

        private final SparseIntArray mModes = new SparseIntArray();

        @Override
        public void onSwitch(int displayId, int magnificationMode) {
            mModes.put(displayId, magnificationMode);
        }

        int getChangedMode(int displayId) {
            return mModes.get(displayId, MODE_INVALID);
        }
    }
}
Loading