Merge "Support individual magnification scale for each display"

This commit is contained in:
Ryan Lin
2021-10-26 14:19:32 +00:00
committed by Android (Google) Code Review
13 changed files with 398 additions and 175 deletions

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -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,

View File

@@ -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);
}
if (mWindowMagnificationMgr != null) {
mWindowMagnificationMgr.setUserId(userId);
}
fullMagnificationController = mFullScreenMagnificationController;
windowMagnificationManager = mWindowMagnificationMgr;
}
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;
}

View File

@@ -0,0 +1,139 @@
/*
* 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);
}
}

View File

@@ -69,7 +69,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
//Ensure the range has consistency with FullScreenMagnificationGestureHandler.
private static final float MIN_SCALE = 2.0f;
private static final float MAX_SCALE = WindowMagnificationManager.MAX_SCALE;
private static final float MAX_SCALE = MagnificationScaleProvider.MAX_SCALE;
private final WindowMagnificationManager mWindowMagnificationMgr;
@VisibleForTesting
@@ -177,8 +177,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
}
final float scale = MathUtils.constrain(
mWindowMagnificationMgr.getPersistedScale(),
MIN_SCALE, MAX_SCALE);
mWindowMagnificationMgr.getPersistedScale(mDisplayId), MIN_SCALE, MAX_SCALE);
mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY);
}

View File

@@ -29,8 +29,6 @@ import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.MathUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.view.MotionEvent;
@@ -40,7 +38,6 @@ import android.view.accessibility.MagnificationAnimationCallback;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -49,6 +46,8 @@ import com.android.server.statusbar.StatusBarManagerInternal;
* A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}
* create by {@link #setConnection(IWindowMagnificationConnection)}. To set the connection with
* SysUI, call {@code StatusBarManagerInternal#requestWindowMagnificationConnection(boolean)}.
* The applied magnification scale is constrained by
* {@link MagnificationScaleProvider#constrainScale(float)}
*/
public class WindowMagnificationManager implements
PanningScalingHandler.MagnificationDelegate {
@@ -57,10 +56,6 @@ public class WindowMagnificationManager implements
private static final String TAG = "WindowMagnificationMgr";
//Ensure the range has consistency with full screen.
static final float MAX_SCALE = FullScreenMagnificationController.MAX_SCALE;
static final float MIN_SCALE = FullScreenMagnificationController.MIN_SCALE;
private final Object mLock = new Object();
private final Context mContext;
@VisibleForTesting
@@ -71,7 +66,6 @@ public class WindowMagnificationManager implements
private ConnectionCallback mConnectionCallback;
@GuardedBy("mLock")
private SparseArray<WindowMagnifier> mWindowMagnifiers = new SparseArray<>();
private int mUserId;
private boolean mReceiverRegistered = false;
@VisibleForTesting
@@ -116,13 +110,14 @@ public class WindowMagnificationManager implements
private final Callback mCallback;
private final AccessibilityTraceManager mTrace;
private final MagnificationScaleProvider mScaleProvider;
public WindowMagnificationManager(Context context, int userId, @NonNull Callback callback,
AccessibilityTraceManager trace) {
AccessibilityTraceManager trace, MagnificationScaleProvider scaleProvider) {
mContext = context;
mUserId = userId;
mCallback = callback;
mTrace = trace;
mScaleProvider = scaleProvider;
}
/**
@@ -158,15 +153,6 @@ public class WindowMagnificationManager implements
}
}
/**
* Sets the currently active user ID.
*
* @param userId the currently active user ID
*/
public void setUserId(int userId) {
mUserId = userId;
}
/**
* @return {@code true} if {@link IWindowMagnificationConnection} is available
*/
@@ -219,13 +205,18 @@ public class WindowMagnificationManager implements
return true;
}
@GuardedBy("mLock")
private void disableAllWindowMagnifiers() {
for (int i = 0; i < mWindowMagnifiers.size(); i++) {
final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i);
magnifier.disableWindowMagnificationInternal(null);
/**
* Disables window magnifier on all displays without animation.
*/
void disableAllWindowMagnifiers() {
synchronized (mLock) {
for (int i = 0; i < mWindowMagnifiers.size(); i++) {
final WindowMagnifier magnifier = mWindowMagnifiers.valueAt(i);
magnifier.disableWindowMagnificationInternal(null);
}
mWindowMagnifiers.clear();
}
mWindowMagnifiers.clear();
}
private void resetWindowMagnifiers() {
@@ -378,29 +369,24 @@ public class WindowMagnificationManager implements
}
/**
* Retrieves a previously persisted magnification scale from the current
* user's settings.
* Retrieves a previously magnification scale from the current
* user's settings. Only the value of the default display is persisted.
*
* @return the previously persisted magnification scale, or the default
* @return the previously magnification scale, or the default
* scale if none is available
*/
float getPersistedScale() {
return Settings.Secure.getFloatForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
MIN_SCALE, mUserId);
float getPersistedScale(int displayId) {
return mScaleProvider.getScale(displayId);
}
/**
* Persists the default display magnification scale to the current user's settings.
* Persists the default display magnification scale to the current user's settings. Only the
* value of the default display is persisted in user's settings.
*/
void persistScale(int displayId) {
float scale = getScale(displayId);
if (scale != 1.0f) {
BackgroundThread.getHandler().post(() -> {
Settings.Secure.putFloatForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, scale, mUserId);
});
mScaleProvider.putScale(scale, displayId);
}
}
@@ -511,7 +497,7 @@ public class WindowMagnificationManager implements
*
* @param displayId The logical display id.
*/
void onDisplayRemoved(int displayId) {
public void onDisplayRemoved(int displayId) {
disableWindowMagnification(displayId, true);
}
@@ -613,7 +599,7 @@ public class WindowMagnificationManager implements
private static class WindowMagnifier {
private final int mDisplayId;
private float mScale = MIN_SCALE;
private float mScale = MagnificationScaleProvider.MIN_SCALE;
private boolean mEnabled;
private final WindowMagnificationManager mWindowMagnificationManager;
@@ -633,7 +619,7 @@ public class WindowMagnificationManager implements
if (mEnabled) {
return false;
}
final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,
centerX, centerY, animationCallback)) {
mScale = normScale;
@@ -664,7 +650,7 @@ public class WindowMagnificationManager implements
if (!mEnabled) {
return;
}
final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
final float normScale = MagnificationScaleProvider.constrainScale(scale);
if (Float.compare(mScale, normScale) != 0
&& mWindowMagnificationManager.setScaleInternal(mDisplayId, scale)) {
mScale = normScale;

View File

@@ -100,7 +100,11 @@ public class FullScreenMagnificationControllerTest {
MagnificationAnimationCallback.class);
private final MagnificationInfoChangedCallback mRequestObserver = mock(
MagnificationInfoChangedCallback.class);
final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
private final MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(
null);
private final MagnificationScaleProvider mScaleProvider = mock(
MagnificationScaleProvider.class);
ValueAnimator mMockValueAnimator;
ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
@@ -123,7 +127,7 @@ public class FullScreenMagnificationControllerTest {
initMockWindowManager();
mFullScreenMagnificationController = new FullScreenMagnificationController(
mMockControllerCtx, new Object(), mRequestObserver);
mMockControllerCtx, new Object(), mRequestObserver, mScaleProvider);
}
@After
@@ -412,12 +416,12 @@ public class FullScreenMagnificationControllerTest {
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter,
FullScreenMagnificationController.MAX_SCALE);
MagnificationScaleProvider.MAX_SCALE);
MagnificationSpec endSpec = getMagnificationSpec(
FullScreenMagnificationController.MAX_SCALE, offsets);
MagnificationScaleProvider.MAX_SCALE, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
FullScreenMagnificationController.MAX_SCALE + 1.0f,
MagnificationScaleProvider.MAX_SCALE + 1.0f,
newCenter.x, newCenter.y, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -631,31 +635,6 @@ public class FullScreenMagnificationControllerTest {
assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
}
@Test
public void testSetUserId_resetsOnlyIfIdChanges() {
for (int i = 0; i < DISPLAY_COUNT; i++) {
testSetUserId_resetsOnlyIfIdChanges(i);
resetMockWindowManager();
}
}
private void testSetUserId_resetsOnlyIfIdChanges(int displayId) {
final int userId1 = 1;
final int userId2 = 2;
register(displayId);
mFullScreenMagnificationController.setUserId(userId1);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
false, SERVICE_ID_1);
mFullScreenMagnificationController.setUserId(userId1);
assertTrue(mFullScreenMagnificationController.isMagnifying(displayId));
mFullScreenMagnificationController.setUserId(userId2);
assertFalse(mFullScreenMagnificationController.isMagnifying(displayId));
}
@Test
public void testResetIfNeeded_doesWhatItSays() {
for (int i = 0; i < DISPLAY_COUNT; i++) {

View File

@@ -22,6 +22,8 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.server.testutils.TestUtils.strictMock;
import static org.junit.Assert.assertFalse;
@@ -38,16 +40,15 @@ import static org.mockito.Mockito.when;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.PointF;
import android.os.Handler;
import android.os.Message;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.accessibility.AccessibilityManagerService;
@@ -60,6 +61,7 @@ import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -121,7 +123,6 @@ public class FullScreenMagnificationGestureHandlerTest {
private static final int DISPLAY_0 = 0;
private Context mContext;
FullScreenMagnificationController mFullScreenMagnificationController;
@Mock
MagnificationGestureHandler.Callback mMockCallback;
@@ -134,6 +135,9 @@ public class FullScreenMagnificationGestureHandlerTest {
@Mock
AccessibilityTraceManager mMockTraceManager;
@Rule
public final TestableContext mContext = new TestableContext(getInstrumentation().getContext());
private OffsettableClock mClock;
private FullScreenMagnificationGestureHandler mMgh;
private TestHandler mHandler;
@@ -143,7 +147,6 @@ public class FullScreenMagnificationGestureHandlerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getContext();
final FullScreenMagnificationController.ControllerContext mockController =
mock(FullScreenMagnificationController.ControllerContext.class);
final WindowManagerInternal mockWindowManager = mock(WindowManagerInternal.class);
@@ -157,14 +160,16 @@ public class FullScreenMagnificationGestureHandlerTest {
when(mockController.getAnimationDuration()).thenReturn(1000L);
when(mockWindowManager.setMagnificationCallbacks(eq(DISPLAY_0), any())).thenReturn(true);
mFullScreenMagnificationController = new FullScreenMagnificationController(mockController,
new Object(), mMagnificationInfoChangedCallback) {
new Object(), mMagnificationInfoChangedCallback,
new MagnificationScaleProvider(mContext)) {
@Override
public boolean magnificationRegionContains(int displayId, float x, float y) {
return true;
}
@Override
void setForceShowMagnifiableBounds(int displayId, boolean show) {}
void setForceShowMagnifiableBounds(int displayId, boolean show) {
}
};
mFullScreenMagnificationController.register(DISPLAY_0);
mClock = new OffsettableClock.Stopped();

View File

@@ -46,6 +46,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.testing.DexmakerShareClassLoaderRule;
import android.view.Display;
import android.view.accessibility.IRemoteMagnificationAnimationCallback;
import android.view.accessibility.MagnificationAnimationCallback;
@@ -58,6 +59,7 @@ import com.android.server.accessibility.AccessibilityTraceManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -79,7 +81,8 @@ public class MagnificationControllerTest {
private static final float MAGNIFIED_CENTER_X = 100;
private static final float MAGNIFIED_CENTER_Y = 200;
private static final float DEFAULT_SCALE = 3f;
private static final int CURRENT_USER_ID = UserHandle.USER_CURRENT;
private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
private static final int SECOND_USER_ID = CURRENT_USER_ID + 1;
private static final int MODE_WINDOW = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
private static final int MODE_FULLSCREEN =
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
@@ -94,6 +97,7 @@ public class MagnificationControllerTest {
private Context mContext;
@Mock
private FullScreenMagnificationController mScreenMagnificationController;
private MagnificationScaleProvider mScaleProvider;
@Captor
private ArgumentCaptor<MagnificationAnimationCallback> mCallbackArgumentCaptor;
@@ -103,6 +107,11 @@ public class MagnificationControllerTest {
private MagnificationController mMagnificationController;
private FullScreenMagnificationControllerStubber mScreenMagnificationControllerStubber;
// To mock package-private class
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -113,15 +122,17 @@ public class MagnificationControllerTest {
Settings.Secure.putFloatForUser(mMockResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, DEFAULT_SCALE,
CURRENT_USER_ID);
mScaleProvider = spy(new MagnificationScaleProvider(mContext));
mWindowMagnificationManager = Mockito.spy(
new WindowMagnificationManager(mContext, CURRENT_USER_ID,
mock(WindowMagnificationManager.Callback.class), mTraceManager));
mock(WindowMagnificationManager.Callback.class), mTraceManager,
mScaleProvider));
mMockConnection = new MockWindowMagnificationConnection(true);
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
mScreenMagnificationControllerStubber = new FullScreenMagnificationControllerStubber(
mScreenMagnificationController);
mMagnificationController = spy(new MagnificationController(mService, new Object(), mContext,
mScreenMagnificationController, mWindowMagnificationManager));
mScreenMagnificationController, mWindowMagnificationManager, mScaleProvider));
mMagnificationController.setMagnificationCapabilities(
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
@@ -283,14 +294,16 @@ public class MagnificationControllerTest {
verify(mScreenMagnificationController).onDisplayRemoved(TEST_DISPLAY);
verify(mWindowMagnificationManager).onDisplayRemoved(TEST_DISPLAY);
verify(mScaleProvider).onDisplayRemoved(TEST_DISPLAY);
}
@Test
public void updateUserIdIfNeeded_AllModulesAvailable_setUserId() {
mMagnificationController.updateUserIdIfNeeded(CURRENT_USER_ID);
public void updateUserIdIfNeeded_AllModulesAvailable_disableMagnificationAndChangeUserId() {
mMagnificationController.updateUserIdIfNeeded(SECOND_USER_ID);
verify(mScreenMagnificationController).setUserId(CURRENT_USER_ID);
verify(mWindowMagnificationManager).setUserId(CURRENT_USER_ID);
verify(mScreenMagnificationController).resetAllIfNeeded(false);
verify(mWindowMagnificationManager).disableAllWindowMagnifiers();
verify(mScaleProvider).onUserChanged(SECOND_USER_ID);
}
@Test
@@ -575,6 +588,13 @@ public class MagnificationControllerTest {
verify(mMagnificationController, never()).logMagnificationModeWithIme(anyInt());
}
@Test
public void onUserRemoved_notifyScaleProvider() {
mMagnificationController.onUserRemoved(SECOND_USER_ID);
verify(mScaleProvider).onUserRemoved(SECOND_USER_ID);
}
private void setMagnificationEnabled(int mode) throws RemoteException {
setMagnificationEnabled(mode, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
}
@@ -627,7 +647,8 @@ public class MagnificationControllerTest {
TEST_DISPLAY);
doAnswer(invocation -> mIsMagnifying).when(
mScreenMagnificationController).isForceShowMagnifiableBounds(TEST_DISPLAY);
doAnswer(invocation -> mScale).when(mScreenMagnificationController).getPersistedScale();
doAnswer(invocation -> mScale).when(mScreenMagnificationController).getPersistedScale(
TEST_DISPLAY);
doAnswer(invocation -> mScale).when(mScreenMagnificationController).getScale(
TEST_DISPLAY);
doAnswer(invocation -> mCenterX).when(mScreenMagnificationController).getCenterX(

View File

@@ -0,0 +1,100 @@
/*
* 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 static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
import android.os.UserHandle;
import android.testing.TestableContext;
import android.view.Display;
import com.android.compatibility.common.util.TestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
/**
* Tests for {@link MagnificationScaleProvider}.
*/
public class MagnificationScaleProviderTest {
private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY + 1;
private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
private static final int SECOND_USER_ID = CURRENT_USER_ID + 1;
private static final float TEST_SCALE = 3;
private static final float DEFAULT_SCALE =
MagnificationScaleProvider.DEFAULT_MAGNIFICATION_SCALE;
@Rule
public final TestableContext mContext = new TestableContext(getInstrumentation().getContext());
private MagnificationScaleProvider mScaleProvider;
@Before
public void setUp() {
mScaleProvider = new MagnificationScaleProvider(mContext);
}
@Test
public void putScaleOnDefaultDisplay_getExpectedValue() throws Exception {
mScaleProvider.putScale(TEST_SCALE, Display.DEFAULT_DISPLAY);
TestUtils.waitUntil("settings value is not changed",
() -> Float.compare(mScaleProvider.getScale(Display.DEFAULT_DISPLAY),
TEST_SCALE) == 0);
}
@Test
public void putScaleOnTestDisplay_getExpectedValue() {
mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
assertEquals(TEST_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
}
@Test
public void onUserChanged_putScale_fallbackToDefaultScale() {
mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
mScaleProvider.onUserChanged(SECOND_USER_ID);
assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
}
@Test
public void onUserRemoved_setScaleOnSecondUser_fallbackToDefaultScale() {
mScaleProvider.onUserChanged(SECOND_USER_ID);
mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
mScaleProvider.onUserChanged(CURRENT_USER_ID);
mScaleProvider.onUserRemoved(SECOND_USER_ID);
// Assume the second user is created with the same id
mScaleProvider.onUserChanged(SECOND_USER_ID);
assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
}
@Test
public void onTestDisplayRemoved_setScaleOnTestDisplay_fallbackToDefaultScale() {
mScaleProvider.putScale(TEST_SCALE, TEST_DISPLAY);
mScaleProvider.onDisplayRemoved(TEST_DISPLAY);
assertEquals(DEFAULT_SCALE, mScaleProvider.getScale(TEST_DISPLAY), 0);
}
}

View File

@@ -21,10 +21,10 @@ import static com.android.server.testutils.TestUtils.strictMock;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.RemoteException;
import android.testing.TestableContext;
import android.util.DebugUtils;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -39,6 +39,7 @@ import com.android.server.accessibility.utils.TouchEventGenerator;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -67,7 +68,10 @@ public class WindowMagnificationGestureHandlerTest {
public static final float DEFAULT_TAP_Y = 299;
private static final int DISPLAY_0 = MockWindowMagnificationConnection.TEST_DISPLAY;
private Context mContext;
@Rule
public final TestableContext mContext = new TestableContext(
InstrumentationRegistry.getInstrumentation().getContext());
private WindowMagnificationManager mWindowMagnificationManager;
private MockWindowMagnificationConnection mMockConnection;
private WindowMagnificationGestureHandler mWindowMagnificationGestureHandler;
@@ -79,9 +83,9 @@ public class WindowMagnificationGestureHandlerTest {
@Before
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mWindowMagnificationManager = new WindowMagnificationManager(mContext, 0,
mock(WindowMagnificationManager.Callback.class), mMockTrace);
mock(WindowMagnificationManager.Callback.class), mMockTrace,
new MagnificationScaleProvider(mContext));
mMockConnection = new MockWindowMagnificationConnection();
mWindowMagnificationGestureHandler = new WindowMagnificationGestureHandler(
mContext, mWindowMagnificationManager, mMockTrace, mMockCallback,

View File

@@ -67,7 +67,7 @@ import org.mockito.invocation.InvocationOnMock;
public class WindowMagnificationManagerTest {
private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
private static final int CURRENT_USER_ID = UserHandle.USER_CURRENT;
private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;
private MockWindowMagnificationConnection mMockConnection;
@Mock
@@ -91,7 +91,7 @@ public class WindowMagnificationManagerTest {
mResolver = new MockContentResolver();
mMockConnection = new MockWindowMagnificationConnection();
mWindowMagnificationManager = new WindowMagnificationManager(mContext, CURRENT_USER_ID,
mMockCallback, mMockTrace);
mMockCallback, mMockTrace, new MagnificationScaleProvider(mContext));
when(mContext.getContentResolver()).thenReturn(mResolver);
doAnswer((InvocationOnMock invocation) -> {
@@ -230,7 +230,7 @@ public class WindowMagnificationManagerTest {
public void getPersistedScale() {
mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
assertEquals(mWindowMagnificationManager.getPersistedScale(), 2.5f);
assertEquals(mWindowMagnificationManager.getPersistedScale(TEST_DISPLAY), 2.5f);
}
@Test
@@ -264,7 +264,7 @@ public class WindowMagnificationManagerTest {
mWindowMagnificationManager.setScale(TEST_DISPLAY, 10.0f);
assertEquals(mWindowMagnificationManager.getScale(TEST_DISPLAY),
WindowMagnificationManager.MAX_SCALE);
MagnificationScaleProvider.MAX_SCALE);
}
@Test