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

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

Merge "Support individual magnification scale for each display"

parents 7bbceb08 35f57381
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.accessibility.magnification.MagnificationController;
import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.accessibility.magnification.MagnificationScaleProvider;
import com.android.server.accessibility.magnification.WindowMagnificationManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -338,7 +339,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
                mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
        mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
        mMagnificationController = new MagnificationController(this, mLock, mContext);
        mMagnificationController = new MagnificationController(this, mLock, mContext,
                new MagnificationScaleProvider(mContext));
        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
        init();
    }
@@ -1364,6 +1366,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
    }

    private void switchUser(int userId) {
        mMagnificationController.updateUserIdIfNeeded(userId);
        synchronized (mLock) {
            if (mCurrentUserId == userId && mInitialized) {
                return;
@@ -1386,8 +1389,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub

            // The user changed.
            mCurrentUserId = userId;

            mMagnificationController.updateUserIdIfNeeded(mCurrentUserId);
            AccessibilityUserState userState = getCurrentUserStateLocked();

            readConfigurationForUserStateLocked(userState);
@@ -1444,6 +1445,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        synchronized (mLock) {
            mUserStates.remove(userId);
        }
        getMagnificationController().onUserRemoved(userId);
    }

    // Called only during settings restore; currently supports only the owner user
+21 −58
Original line number Diff line number Diff line
@@ -28,10 +28,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.MathUtils;
import android.util.Slog;
@@ -59,7 +57,8 @@ import java.util.Locale;
 * holding the current state of magnification and animation, and it handles
 * communication between the accessibility manager and window manager.
 *
 * Magnification is limited to the range [MIN_SCALE, MAX_SCALE], and can only occur inside the
 * Magnification is limited to the range controlled by
 * {@link MagnificationScaleProvider#constrainScale(float)}, and can only occur inside the
 * magnification region. If a value is out of bounds, it will be adjusted to guarantee these
 * constraints.
 */
@@ -69,13 +68,9 @@ public class FullScreenMagnificationController {

    private static final MagnificationAnimationCallback STUB_ANIMATION_CALLBACK = success -> {
    };
    public static final float MIN_SCALE = 1.0f;
    public static final float MAX_SCALE = 8.0f;

    private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;

    private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;

    private final Object mLock;

    private final ControllerContext mControllerCtx;
@@ -84,7 +79,7 @@ public class FullScreenMagnificationController {

    private final MagnificationInfoChangedCallback mMagnificationInfoChangedCallback;

    private int mUserId;
    private final MagnificationScaleProvider mScaleProvider;

    private final long mMainThreadId;

@@ -489,7 +484,7 @@ public class FullScreenMagnificationController {
                return false;
            }
            // Constrain scale immediately for use in the pivot calculations.
            scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
            scale = MagnificationScaleProvider.constrainScale(scale);

            final Rect viewport = mTempRect;
            mMagnificationRegion.getBounds(viewport);
@@ -557,7 +552,7 @@ public class FullScreenMagnificationController {
            // Compute changes.
            boolean changed = false;

            final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
            final float normScale = MagnificationScaleProvider.constrainScale(scale);
            if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
                mCurrentMagnificationSpec.scale = normScale;
                changed = true;
@@ -658,12 +653,13 @@ public class FullScreenMagnificationController {
     */
    public FullScreenMagnificationController(@NonNull Context context,
            @NonNull AccessibilityManagerService ams, @NonNull Object lock,
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
            @NonNull MagnificationScaleProvider scaleProvider) {
        this(new ControllerContext(context, ams,
                LocalServices.getService(WindowManagerInternal.class),
                new Handler(context.getMainLooper()),
                context.getResources().getInteger(R.integer.config_longAnimTime)), lock,
                magnificationInfoChangedCallback);
                magnificationInfoChangedCallback, scaleProvider);
    }

    /**
@@ -672,12 +668,14 @@ public class FullScreenMagnificationController {
    @VisibleForTesting
    public FullScreenMagnificationController(@NonNull ControllerContext ctx,
            @NonNull Object lock,
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback) {
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
            @NonNull MagnificationScaleProvider scaleProvider) {
        mControllerCtx = ctx;
        mLock = lock;
        mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
        mScreenStateObserver = new ScreenStateObserver(mControllerCtx.getContext(), this);
        mMagnificationInfoChangedCallback = magnificationInfoChangedCallback;
        mScaleProvider = scaleProvider;
    }

    /**
@@ -1096,18 +1094,9 @@ public class FullScreenMagnificationController {
    /**
     * Persists the default display magnification scale to the current user's settings.
     */
    public void persistScale() {
        // TODO: b/123047354, Need support multi-display?
    public void persistScale(int displayId) {
        final float scale = getScale(Display.DEFAULT_DISPLAY);
        final int userId = mUserId;

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                mControllerCtx.putMagnificationScale(scale, userId);
                return null;
            }
        }.execute();
        mScaleProvider.putScale(scale, displayId);
    }

    /**
@@ -1117,21 +1106,8 @@ public class FullScreenMagnificationController {
     * @return the previously persisted magnification scale, or the default
     *         scale if none is available
     */
    public float getPersistedScale() {
        return mControllerCtx.getMagnificationScale(mUserId);
    }

    /**
     * Sets the currently active user ID.
     *
     * @param userId the currently active user ID
     */
    public void setUserId(int userId) {
        if (mUserId == userId) {
            return;
        }
        mUserId = userId;
        resetAllIfNeeded(false);
    public float getPersistedScale(int displayId) {
        return mScaleProvider.getScale(displayId);
    }

    /**
@@ -1225,7 +1201,11 @@ public class FullScreenMagnificationController {
        mControllerCtx.getHandler().sendMessage(m);
    }

    private void resetAllIfNeeded(boolean animate) {
    /**
     * Resets magnification on all displays.
     * @param animate reset the magnification with animation
     */
    void resetAllIfNeeded(boolean animate) {
        synchronized (mLock) {
            for (int i = 0; i < mDisplays.size(); i++) {
                resetIfNeeded(mDisplays.keyAt(i), animate);
@@ -1288,8 +1268,8 @@ public class FullScreenMagnificationController {
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("MagnificationController[");
        builder.append("mUserId=").append(mUserId);
        builder.append(", mDisplays=").append(mDisplays);
        builder.append(", mScaleProvider=").append(mScaleProvider);
        builder.append("]");
        return builder.toString();
    }
@@ -1569,23 +1549,6 @@ public class FullScreenMagnificationController {
            return new ValueAnimator();
        }

        /**
         * Write Settings of magnification scale.
         */
        public void putMagnificationScale(float value, int userId) {
            Settings.Secure.putFloatForUser(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
        }

        /**
         * Get Settings of magnification scale.
         */
        public float getMagnificationScale(int userId) {
            return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                    DEFAULT_MAGNIFICATION_SCALE, userId);
        }

        /**
         * @return Configuration of animation duration.
         */
+4 −4
Original line number Diff line number Diff line
@@ -119,11 +119,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
    private static final boolean DEBUG_DETECTING = false | DEBUG_ALL;
    private static final boolean DEBUG_PANNING_SCALING = false | DEBUG_ALL;

    // The MIN_SCALE is different from MagnificationController.MIN_SCALE due
    // The MIN_SCALE is different from MagnificationScaleProvider.MIN_SCALE due
    // to AccessibilityService.MagnificationController#setScale() has
    // different scale range
    private static final float MIN_SCALE = 2.0f;
    private static final float MAX_SCALE = FullScreenMagnificationController.MAX_SCALE;
    private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;

    @VisibleForTesting final FullScreenMagnificationController mFullScreenMagnificationController;

@@ -341,7 +341,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
        }

        public void persistScaleAndTransitionTo(State state) {
            mFullScreenMagnificationController.persistScale();
            mFullScreenMagnificationController.persistScale(mDisplayId);
            clear();
            transitionTo(state);
        }
@@ -945,7 +945,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
        if (DEBUG_DETECTING) Slog.i(mLogTag, "zoomOn(" + centerX + ", " + centerY + ")");

        final float scale = MathUtils.constrain(
                mFullScreenMagnificationController.getPersistedScale(),
                mFullScreenMagnificationController.getPersistedScale(mDisplayId),
                MIN_SCALE, MAX_SCALE);
        mFullScreenMagnificationController.setScaleAndCenter(mDisplayId,
                scale, centerX, centerY,
+38 −13
Original line number Diff line number Diff line
@@ -23,11 +23,13 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
@@ -75,12 +77,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    private final SparseArray<DisableMagnificationCallback>
            mMagnificationEndRunnableSparseArray = new SparseArray();

    private final MagnificationScaleProvider mScaleProvider;
    private FullScreenMagnificationController mFullScreenMagnificationController;
    private WindowMagnificationManager mWindowMagnificationMgr;
    private int mMagnificationCapabilities = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;

    @GuardedBy("mLock")
    private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
    // Track the active user to reset the magnification and get the associated user settings.
    private @UserIdInt int mUserId = UserHandle.USER_SYSTEM;
    @GuardedBy("mLock")
    private boolean mImeWindowVisible = false;
    private long mWindowModeEnabledTime = 0;
@@ -98,17 +103,19 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    }

    public MagnificationController(AccessibilityManagerService ams, Object lock,
            Context context) {
            Context context, MagnificationScaleProvider scaleProvider) {
        mAms = ams;
        mLock = lock;
        mContext = context;
        mScaleProvider = scaleProvider;
    }

    @VisibleForTesting
    public MagnificationController(AccessibilityManagerService ams, Object lock,
            Context context, FullScreenMagnificationController fullScreenMagnificationController,
            WindowMagnificationManager windowMagnificationManager) {
        this(ams, lock, context);
            WindowMagnificationManager windowMagnificationManager,
            MagnificationScaleProvider scaleProvider) {
        this(ams, lock, context, scaleProvider);
        mFullScreenMagnificationController = fullScreenMagnificationController;
        mWindowMagnificationMgr = windowMagnificationManager;
    }
@@ -194,7 +201,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        final FullScreenMagnificationController screenMagnificationController =
                getFullScreenMagnificationController();
        final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
        final float scale = windowMagnificationMgr.getPersistedScale();
        final float scale = mScaleProvider.getScale(displayId);
        final DisableMagnificationCallback animationEndCallback =
                new DisableMagnificationCallback(transitionCallBack, displayId, targetMode,
                        scale, magnificationCenter);
@@ -313,13 +320,23 @@ public class MagnificationController implements WindowMagnificationManager.Callb
     * @param userId the currently active user ID
     */
    public void updateUserIdIfNeeded(int userId) {
        if (mUserId == userId) {
            return;
        }
        mUserId = userId;
        final FullScreenMagnificationController fullMagnificationController;
        final WindowMagnificationManager windowMagnificationManager;
        synchronized (mLock) {
            if (mFullScreenMagnificationController != null) {
                mFullScreenMagnificationController.setUserId(userId);
            fullMagnificationController = mFullScreenMagnificationController;
            windowMagnificationManager = mWindowMagnificationMgr;
        }
            if (mWindowMagnificationMgr != null) {
                mWindowMagnificationMgr.setUserId(userId);

        mScaleProvider.onUserChanged(userId);
        if (fullMagnificationController != null) {
            fullMagnificationController.resetAllIfNeeded(false);
        }
        if (windowMagnificationManager != null) {
            windowMagnificationManager.disableAllWindowMagnifiers();
        }
    }

@@ -337,6 +354,14 @@ public class MagnificationController implements WindowMagnificationManager.Callb
                mWindowMagnificationMgr.onDisplayRemoved(displayId);
            }
        }
        mScaleProvider.onDisplayRemoved(displayId);
    }

    /**
     * Called when the given user is removed.
     */
    public void onUserRemoved(int userId) {
        mScaleProvider.onUserRemoved(userId);
    }

    public void setMagnificationCapabilities(int capabilities) {
@@ -378,8 +403,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        synchronized (mLock) {
            if (mFullScreenMagnificationController == null) {
                mFullScreenMagnificationController = new FullScreenMagnificationController(mContext,
                        mAms, mLock, this);
                mFullScreenMagnificationController.setUserId(mAms.getCurrentUserIdLocked());
                        mAms, mLock, this, mScaleProvider);
            }
        }
        return mFullScreenMagnificationController;
@@ -404,7 +428,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
        synchronized (mLock) {
            if (mWindowMagnificationMgr == null) {
                mWindowMagnificationMgr = new WindowMagnificationManager(mContext,
                        mAms.getCurrentUserIdLocked(), this, mAms.getTraceManager());
                        mUserId, this, mAms.getTraceManager(),
                        mScaleProvider);
            }
            return mWindowMagnificationMgr;
        }
+139 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.server.accessibility.magnification;

import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.MathUtils;
import android.util.SparseArray;
import android.view.Display;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;

/**
 * Supplies setter/getter of the magnification scale for the given display. Only the value of the
 * default play is persisted. It also constraints the range of applied magnification scale between
 * [MIN_SCALE, MAX_SCALE] which is consistent with the range provided by
 * {@code AccessibilityService.MagnificationController#setScale()}.
 */
public class MagnificationScaleProvider {

    @VisibleForTesting
    protected static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
    public static final float MIN_SCALE = 1.0f;
    public static final float MAX_SCALE = 8.0f;

    private final Context mContext;
    // Stores the scale for non-default displays.
    @GuardedBy("mLock")
    private final SparseArray<SparseArray<Float>> mUsersScales = new SparseArray();
    private int mCurrentUserId = UserHandle.USER_SYSTEM;
    private final Object mLock = new Object();

    public MagnificationScaleProvider(Context context) {
        mContext = context;
    }

    /**
     *  Stores the user settings scale associated to the given display. Only the scale of the
     *  default display is persistent.
     *
     * @param scale the magnification scale
     * @param displayId the id of the display
     */
    void putScale(float scale, int displayId) {
        if (displayId == Display.DEFAULT_DISPLAY) {
            BackgroundThread.getHandler().post(
                    () -> Settings.Secure.putFloatForUser(mContext.getContentResolver(),
                            Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale,
                            mCurrentUserId));
        } else {
            synchronized (mLock) {
                getScalesWithCurrentUser().put(displayId, scale);
            }
        }
    }

    /**
     * Gets the user settings scale with the given display.
     *
     * @param displayId the id of the display
     * @return the magnification scale.
     */
    float getScale(int displayId) {
        if (displayId == Display.DEFAULT_DISPLAY) {
            return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                    DEFAULT_MAGNIFICATION_SCALE, mCurrentUserId);
        } else {
            synchronized (mLock) {
                return getScalesWithCurrentUser().get(displayId, DEFAULT_MAGNIFICATION_SCALE);
            }
        }
    }


    @GuardedBy("mLock")
    private SparseArray<Float> getScalesWithCurrentUser() {
        SparseArray<Float> scales = mUsersScales.get(mCurrentUserId);
        if (scales == null) {
            scales = new SparseArray<>();
            mUsersScales.put(mCurrentUserId, scales);
        }

        return scales;
    }

    void onUserChanged(int userId) {
        synchronized (mLock) {
            mCurrentUserId = userId;
        }
    }

    void onUserRemoved(int userId) {
        synchronized (mLock) {
            mUsersScales.remove(userId);
        }
    }

    void onDisplayRemoved(int displayId) {
        synchronized (mLock) {
            final int userCounts = mUsersScales.size();
            for (int i = userCounts - 1; i >= 0; i--) {
                mUsersScales.get(i).remove(displayId);
            }
        }
    }

    @Override
    public String toString() {
        synchronized (mLock) {
            return "MagnificationScaleProvider{"
                    + "mCurrentUserId=" + mCurrentUserId
                    + "Scale on the default display=" + getScale(Display.DEFAULT_DISPLAY)
                    + "Scales on non-default displays=" + getScalesWithCurrentUser()
                    + '}';
        }
    }

    static float constrainScale(float scale) {
        return MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
    }
}
Loading