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

Commit b7c20172 authored by Roy Chou's avatar Roy Chou
Browse files

feat(#MagSettingsPanel): add MagnificationSettingsController to interact with...

feat(#MagSettingsPanel): add MagnificationSettingsController to interact with WindowMagnificationSetting

We separate WindowMagnificationSettings from WindowMagnificationController and use a new class MagnificationSettingsController to hold and interact with the settings panel. Besides, Use DisplayIdIndexSupplier in WindowMagnification to access MagnificationSettingsController and handle controller callbacks.

Since the WindowMagnificationSettings is split from WindowMagnificationController, WindowMagnificationController can not trigger show/hide settings panel directly. Therefore, we add onClickSettingsButton callback in WindowMagnifierCallback so that WindowMagnification could receive the button clicked event then trigger the MagnificationSettingsController to show the panel. Also, we add hideMagnificationSettingsPanel method in WindowMagnification, and it can be triggered by framwork service side (in next submitted-together cl).

Bug: 271127581
Test: manually
      atest MagnificationSettingsControllerTest
      atest WindowMagnificationAnimationControllerTest
      atest WindowMagnificationControllerTest
      atest WindowMagnificationTest
Change-Id: Ibf3de2eb00a58b8375683c6e5f1e5d4239ab8a31
parent dc8992c4
Loading
Loading
Loading
Loading
+210 −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.android.systemui.accessibility.WindowMagnificationSettings.MagnificationSize;

import android.annotation.NonNull;
import android.annotation.UiContext;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.util.Range;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.util.settings.SecureSettings;

/**
 * A class to control {@link WindowMagnificationSettings} and receive settings panel callbacks by
 * {@link WindowMagnificationSettingsCallback}.
 * The settings panel callbacks will be delegated through
 * {@link MagnificationSettingsController.Callback} to {@link WindowMagnification}.
 */

public class MagnificationSettingsController implements ComponentCallbacks {

    // It should be consistent with the value defined in WindowMagnificationGestureHandler.
    private static final Range<Float> A11Y_ACTION_SCALE_RANGE = new Range<>(1.0f, 8.0f);

    private final Context mContext;

    private final int mDisplayId;

    @NonNull
    private final Callback mSettingsControllerCallback;

    // Window Magnification Setting view
    private WindowMagnificationSettings mWindowMagnificationSettings;

    private final Configuration mConfiguration;

    MagnificationSettingsController(
            @UiContext Context context,
            SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
            @NonNull Callback settingsControllerCallback,
            SecureSettings secureSettings) {
        this(context, sfVsyncFrameProvider, settingsControllerCallback,  secureSettings, null);
    }

    @VisibleForTesting
    MagnificationSettingsController(
            @UiContext Context context,
            SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
            @NonNull Callback settingsControllerCallback,
            SecureSettings secureSettings,
            WindowMagnificationSettings windowMagnificationSettings) {
        mContext = context;
        mDisplayId = mContext.getDisplayId();
        mConfiguration = new Configuration(context.getResources().getConfiguration());
        mSettingsControllerCallback = settingsControllerCallback;
        if (windowMagnificationSettings != null) {
            mWindowMagnificationSettings = windowMagnificationSettings;
        } else {
            mWindowMagnificationSettings = new WindowMagnificationSettings(context,
                    mWindowMagnificationSettingsCallback,
                    sfVsyncFrameProvider, secureSettings);
        }
    }

    void showMagnificationSettings() {
        if (!mWindowMagnificationSettings.isSettingPanelShowing()) {
            onConfigurationChanged(mContext.getResources().getConfiguration());
            mContext.registerComponentCallbacks(this);
        }
        mWindowMagnificationSettings.showSettingPanel();
    }

    void closeMagnificationSettings() {
        mContext.unregisterComponentCallbacks(this);
        mWindowMagnificationSettings.hideSettingPanel();
    }

    boolean isMagnificationSettingsShowing() {
        return mWindowMagnificationSettings.isSettingPanelShowing();
    }

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

    @VisibleForTesting
    void onConfigurationChanged(int configDiff) {
        mWindowMagnificationSettings.onConfigurationChanged(configDiff);
    }

    @Override
    public void onLowMemory() {

    }

    interface Callback {

        /**
         * Called when change magnification size.
         *
         * @param displayId The logical display id.
         * @param index Magnification size index.
         *     0 : MagnificationSize.NONE,
         *     1 : MagnificationSize.SMALL,
         *     2 : MagnificationSize.MEDIUM,
         *     3 : MagnificationSize.LARGE,
         *     4 : MagnificationSize.FULLSCREEN
         */
        void onSetMagnifierSize(int displayId, @MagnificationSize int index);

        /**
         * Called when set allow diagonal scrolling.
         *
         * @param displayId The logical display id.
         * @param enable Allow diagonal scrolling enable value.
         */
        void onSetDiagonalScrolling(int displayId, boolean enable);

        /**
         * Called when change magnification size on free mode.
         *
         * @param displayId The logical display id.
         * @param enable Free mode enable value.
         */
        void onEditMagnifierSizeMode(int displayId, boolean enable);

        /**
         * Called when set magnification scale.
         *
         * @param displayId The logical display id.
         * @param scale Magnification scale value.
         */
        void onMagnifierScale(int displayId, float scale);

        /**
         * Called when magnification mode changed.
         *
         * @param displayId The logical display id.
         * @param newMode Magnification mode
         *      1 : ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
         *      2 : ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
         */
        void onModeSwitch(int displayId, int newMode);

        /**
         * Called when the visibility of the magnification settings panel changed.
         *
         * @param displayId The logical display id.
         * @param shown The visibility of the magnification settings panel.
         */
        void onSettingsPanelVisibilityChanged(int displayId, boolean shown);
    }

    @VisibleForTesting
    final WindowMagnificationSettingsCallback mWindowMagnificationSettingsCallback =
            new WindowMagnificationSettingsCallback() {
                @Override
        public void onSetDiagonalScrolling(boolean enable) {
            mSettingsControllerCallback.onSetDiagonalScrolling(mDisplayId, enable);
        }

        @Override
        public void onModeSwitch(int newMode) {
            mSettingsControllerCallback.onModeSwitch(mDisplayId, newMode);
        }

        @Override
        public void onSettingsPanelVisibilityChanged(boolean shown) {
            mSettingsControllerCallback.onSettingsPanelVisibilityChanged(mDisplayId, shown);
        }

        @Override
        public void onSetMagnifierSize(@MagnificationSize int index) {
            mSettingsControllerCallback.onSetMagnifierSize(mDisplayId, index);
        }

        @Override
        public void onEditMagnifierSizeMode(boolean enable) {
            mSettingsControllerCallback.onEditMagnifierSizeMode(mDisplayId, enable);
        }

        @Override
        public void onMagnifierScale(float scale) {
            mSettingsControllerCallback.onMagnifierScale(mDisplayId,
                    A11Y_ACTION_SCALE_RANGE.clamp(scale));
        }
    };
}
+200 −30
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.accessibility;

import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;

import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
@@ -55,8 +56,7 @@ import javax.inject.Inject;
 * when {@code IStatusBar#requestWindowMagnificationConnection(boolean)} is called.
 */
@SysUISingleton
public class WindowMagnification implements CoreStartable, WindowMagnifierCallback,
        CommandQueue.Callbacks {
public class WindowMagnification implements CoreStartable, CommandQueue.Callbacks {
    private static final String TAG = "WindowMagnification";

    private final ModeSwitchesController mModeSwitchesController;
@@ -113,11 +113,45 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba
    @VisibleForTesting
    DisplayIdIndexSupplier<WindowMagnificationController> mMagnificationControllerSupplier;

    private static class SettingsSupplier extends
            DisplayIdIndexSupplier<MagnificationSettingsController> {

        private final Context mContext;
        private final MagnificationSettingsController.Callback mSettingsControllerCallback;
        private final SecureSettings mSecureSettings;

        SettingsSupplier(Context context,
                MagnificationSettingsController.Callback settingsControllerCallback,
                DisplayManager displayManager,
                SecureSettings secureSettings) {
            super(displayManager);
            mContext = context;
            mSettingsControllerCallback = settingsControllerCallback;
            mSecureSettings = secureSettings;
        }

        @Override
        protected MagnificationSettingsController createInstance(Display display) {
            final Context windowContext = mContext.createWindowContext(display,
                    TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null);
            windowContext.setTheme(com.android.systemui.R.style.Theme_SystemUI);
            return new MagnificationSettingsController(
                    windowContext,
                    new SfVsyncFrameCallbackProvider(),
                    mSettingsControllerCallback,
                    mSecureSettings);
        }
    }

    @VisibleForTesting
    DisplayIdIndexSupplier<MagnificationSettingsController> mMagnificationSettingsSupplier;

    @Inject
    public WindowMagnification(Context context, @Main Handler mainHandler,
            CommandQueue commandQueue, ModeSwitchesController modeSwitchesController,
            SysUiState sysUiState, OverviewProxyService overviewProxyService,
            SecureSettings secureSettings, DisplayTracker displayTracker) {
            SecureSettings secureSettings, DisplayTracker displayTracker,
            DisplayManager displayManager) {
        mContext = context;
        mHandler = mainHandler;
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
@@ -127,8 +161,10 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba
        mOverviewProxyService = overviewProxyService;
        mDisplayTracker = displayTracker;
        mMagnificationControllerSupplier = new ControllerSupplier(context,
                mHandler, this, context.getSystemService(DisplayManager.class), sysUiState,
                secureSettings);
                mHandler, mWindowMagnifierCallback,
                displayManager, sysUiState, secureSettings);
        mMagnificationSettingsSupplier = new SettingsSupplier(context,
                mMagnificationSettingsControllerCallback, displayManager, secureSettings);
    }

    @Override
@@ -209,6 +245,50 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba
        }
    }

    @MainThread
    void showMagnificationSettingsPanel(int displayId) {
        final MagnificationSettingsController magnificationSettingsController =
                mMagnificationSettingsSupplier.get(displayId);
        if (magnificationSettingsController != null) {
            magnificationSettingsController.showMagnificationSettings();
        }
    }

    @MainThread
    void hideMagnificationSettingsPanel(int displayId) {
        final MagnificationSettingsController magnificationSettingsController =
                mMagnificationSettingsSupplier.get(displayId);
        if (magnificationSettingsController != null) {
            magnificationSettingsController.closeMagnificationSettings();
        }
    }

    boolean isMagnificationSettingsPanelShowing(int displayId) {
        final MagnificationSettingsController magnificationSettingsController =
                mMagnificationSettingsSupplier.get(displayId);
        if (magnificationSettingsController != null) {
            return magnificationSettingsController.isMagnificationSettingsShowing();
        }
        return false;
    }

    @MainThread
    void showMagnificationButton(int displayId, int magnificationMode) {
        // not to show mode switch button if settings panel is already showing to
        // prevent settings panel be covered by the button.
        if (isMagnificationSettingsPanelShowing(displayId)) {
            return;
        }
        mModeSwitchesController.showButton(displayId, magnificationMode);
    }

    @MainThread
    void removeMagnificationButton(int displayId) {
        mModeSwitchesController.removeButton(displayId);
    }

    @VisibleForTesting
    final WindowMagnifierCallback mWindowMagnifierCallback = new WindowMagnifierCallback() {
        @Override
        public void onWindowMagnifierBoundsChanged(int displayId, Rect frame) {
            if (mWindowMagnificationConnectionImpl != null) {
@@ -244,12 +324,102 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba
            }
        }

        @Override
        public void onClickSettingsButton(int displayId) {
            mHandler.post(() -> showMagnificationSettingsPanel(displayId));
        }
    };

    @VisibleForTesting
    final MagnificationSettingsController.Callback mMagnificationSettingsControllerCallback =
            new MagnificationSettingsController.Callback() {
        @Override
        public void onSetMagnifierSize(int displayId, int index) {
            mHandler.post(() -> onSetMagnifierSizeInternal(displayId, index));
        }

        @Override
        public void onSetDiagonalScrolling(int displayId, boolean enable) {
            mHandler.post(() -> onSetDiagonalScrollingInternal(displayId, enable));
        }

        @Override
        public void onEditMagnifierSizeMode(int displayId, boolean enable) {
            mHandler.post(() -> onEditMagnifierSizeModeInternal(displayId, enable));
        }

        @Override
        public void onMagnifierScale(int displayId, float scale) {
            if (mWindowMagnificationConnectionImpl != null) {
                mWindowMagnificationConnectionImpl.onPerformScaleAction(displayId, scale);
            }
        }

        @Override
        public void onModeSwitch(int displayId, int newMode) {
            mHandler.post(() -> onModeSwitchInternal(displayId, newMode));
        }

        @Override
        public void onSettingsPanelVisibilityChanged(int displayId, boolean shown) {
            mHandler.post(() -> onSettingsPanelVisibilityChangedInternal(displayId, shown));
        }
    };

    @MainThread
    private void onSetMagnifierSizeInternal(int displayId, int index) {
        final WindowMagnificationController windowMagnificationController =
                mMagnificationControllerSupplier.get(displayId);
        if (windowMagnificationController != null) {
            windowMagnificationController.changeMagnificationSize(index);
        }
    }

    @MainThread
    private void onSetDiagonalScrollingInternal(int displayId, boolean enable) {
        final WindowMagnificationController windowMagnificationController =
                mMagnificationControllerSupplier.get(displayId);
        if (windowMagnificationController != null) {
            windowMagnificationController.setDiagonalScrolling(enable);
        }
    }

    @MainThread
    private void onEditMagnifierSizeModeInternal(int displayId, boolean enable) {
        final WindowMagnificationController windowMagnificationController =
                mMagnificationControllerSupplier.get(displayId);
        if (windowMagnificationController != null && windowMagnificationController.isActivated()) {
            windowMagnificationController.setEditMagnifierSizeMode(enable);
        }
    }

    @MainThread
    private void onModeSwitchInternal(int displayId, int newMode) {
        final WindowMagnificationController windowMagnificationController =
                mMagnificationControllerSupplier.get(displayId);
        final boolean isWindowMagnifierActivated = windowMagnificationController.isActivated();
        final boolean isSwitchToWindowMode = (newMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
        final boolean changed = isSwitchToWindowMode ^ isWindowMagnifierActivated;
        if (changed) {
            final MagnificationSettingsController magnificationSettingsController =
                    mMagnificationSettingsSupplier.get(displayId);
            if (magnificationSettingsController != null) {
                magnificationSettingsController.closeMagnificationSettings();
            }
            if (mWindowMagnificationConnectionImpl != null) {
                mWindowMagnificationConnectionImpl.onChangeMagnificationMode(displayId, newMode);
            }
        }
    }

    @MainThread
    private void onSettingsPanelVisibilityChangedInternal(int displayId, boolean shown) {
        final WindowMagnificationController windowMagnificationController =
                mMagnificationControllerSupplier.get(displayId);
        if (windowMagnificationController != null) {
            windowMagnificationController.updateDragHandleResourcesIfNeeded(shown);
        }
    }

    @Override
    public void requestWindowMagnificationConnection(boolean connect) {
@@ -270,7 +440,7 @@ public class WindowMagnification implements CoreStartable, WindowMagnifierCallba
    private void setWindowMagnificationConnection() {
        if (mWindowMagnificationConnectionImpl == null) {
            mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this,
                    mHandler, mModeSwitchesController);
                    mHandler);
        }
        mModeSwitchesController.setSwitchListenerDelegate(
                mWindowMagnificationConnectionImpl::onChangeMagnificationMode);
+3 −5
Original line number Diff line number Diff line
@@ -39,13 +39,11 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S
    private IWindowMagnificationConnectionCallback mConnectionCallback;
    private final WindowMagnification mWindowMagnification;
    private final Handler mHandler;
    private final ModeSwitchesController mModeSwitchesController;

    WindowMagnificationConnectionImpl(@NonNull WindowMagnification windowMagnification,
            @Main Handler mainHandler, ModeSwitchesController modeSwitchesController) {
            @Main Handler mainHandler) {
        mWindowMagnification = windowMagnification;
        mHandler = mainHandler;
        mModeSwitchesController = modeSwitchesController;
    }

    @Override
@@ -86,13 +84,13 @@ class WindowMagnificationConnectionImpl extends IWindowMagnificationConnection.S
    @Override
    public void showMagnificationButton(int displayId, int magnificationMode) {
        mHandler.post(
                () -> mModeSwitchesController.showButton(displayId, magnificationMode));
                () -> mWindowMagnification.showMagnificationButton(displayId, magnificationMode));
    }

    @Override
    public void removeMagnificationButton(int displayId) {
        mHandler.post(
                () -> mModeSwitchesController.removeButton(displayId));
                () -> mWindowMagnification.removeMagnificationButton(displayId));
    }

    @Override
+28 −96

File changed.

Preview size limit exceeded, changes collapsed.

+4 −0
Original line number Diff line number Diff line
@@ -322,6 +322,10 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
        showSettingPanel(true);
    }

    public boolean isSettingPanelShowing() {
        return mIsVisible;
    }

    public void setScaleSeekbar(float scale) {
        setSeekbarProgress(scale);
    }
Loading