Merge "Fix several accessibility magnification issues." into nyc-dev

am: 1f70f0b

* commit '1f70f0b7d60ad0b98fe6597162769bce8b85e3ed':
  Fix several accessibility magnification issues.

Change-Id: I27ff667fd57dcde82ba92342641f2c83e08762be
This commit is contained in:
Phil Weaver
2016-04-27 22:59:58 +00:00
committed by android-build-merger
10 changed files with 313 additions and 241 deletions

View File

@@ -2699,7 +2699,7 @@ package android.accessibilityservice {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
method public float getCenterX();
method public float getCenterY();
method public android.graphics.Region getMagnifiedRegion();
method public android.graphics.Region getMagnificationRegion();
method public float getScale();
method public boolean removeListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public boolean reset(boolean);

View File

@@ -2810,7 +2810,7 @@ package android.accessibilityservice {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
method public float getCenterX();
method public float getCenterY();
method public android.graphics.Region getMagnifiedRegion();
method public android.graphics.Region getMagnificationRegion();
method public float getScale();
method public boolean removeListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public boolean reset(boolean);

View File

@@ -2699,7 +2699,7 @@ package android.accessibilityservice {
method public void addListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener, android.os.Handler);
method public float getCenterX();
method public float getCenterY();
method public android.graphics.Region getMagnifiedRegion();
method public android.graphics.Region getMagnificationRegion();
method public float getScale();
method public boolean removeListener(android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener);
method public boolean reset(boolean);

View File

@@ -925,18 +925,25 @@ public abstract class AccessibilityService extends Service {
}
/**
* Returns the region of the screen currently being magnified. If
* magnification is not enabled, the returned region will be empty.
* Returns the region of the screen currently active for magnification. Changes to
* magnification scale and center only affect this portion of the screen. The rest of the
* screen, for example input methods, cannot be magnified. This region is relative to the
* unscaled screen and is independent of the scale and center point.
* <p>
* The returned region will be empty if magnification is not active. Magnification is active
* if magnification gestures are enabled or if a service is running that can control
* magnification.
* <p>
* <strong>Note:</strong> If the service is not yet connected (e.g.
* {@link AccessibilityService#onServiceConnected()} has not yet been
* called) or the service has been disconnected, this method will
* return an empty region.
*
* @return the screen-relative bounds of the magnified region
* @return the region of the screen currently active for magnification, or an empty region
* if magnification is not active.
*/
@NonNull
public Region getMagnifiedRegion() {
public Region getMagnificationRegion() {
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
mService.mConnectionId);
@@ -1049,11 +1056,12 @@ public abstract class AccessibilityService extends Service {
* Called when the magnified region, scale, or center changes.
*
* @param controller the magnification controller
* @param region the new magnified region, may be empty if
* magnification is not enabled (e.g. scale is 1)
* @param region the magnification region
* @param scale the new scale
* @param centerX the new X coordinate around which magnification is focused
* @param centerY the new Y coordinate around which magnification is focused
* @param centerX the new X coordinate, in unscaled coordinates, around which
* magnification is focused
* @param centerY the new Y coordinate, in unscaled coordinates, around which
* magnification is focused
*/
void onMagnificationChanged(@NonNull MagnificationController controller,
@NonNull Region region, float scale, float centerX, float centerY);

View File

@@ -54,13 +54,12 @@ public abstract class WindowManagerInternal {
public interface MagnificationCallbacks {
/**
* Called when the bounds of the screen content that is magnified changed.
* Note that not the entire screen is magnified.
* Called when the region where magnification operates changes. Note that this isn't the
* entire screen. For example, IMEs are not magnified.
*
* @param magnifiedBounds the currently magnified region
* @param availableBounds the region available for magnification
* @param magnificationRegion the current magnification region
*/
public void onMagnifiedBoundsChanged(Region magnifiedBounds, Region availableBounds);
public void onMagnificationRegionChanged(Region magnificationRegion);
/**
* Called when an application requests a rectangle on the screen to allow
@@ -158,13 +157,11 @@ public abstract class WindowManagerInternal {
public abstract void setMagnificationSpec(MagnificationSpec spec);
/**
* Obtains the magnified and available regions.
* Obtains the magnification regions.
*
* @param outMagnified the currently magnified region
* @param outAvailable the region available for magnification
* @param magnificationRegion the current magnification region
*/
public abstract void getMagnificationRegions(@NonNull Region outMagnified,
@NonNull Region outAvailable);
public abstract void getMagnificationRegion(@NonNull Region magnificationRegion);
/**
* Gets the magnification and translation applied to a window given its token.

View File

@@ -151,7 +151,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private static final int WINDOW_ID_UNKNOWN = -1;
private static int sIdCounter = 0;
// Each service has an ID. Also provide one for magnification gesture handling
public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1;
private static int sNextWindowId;
@@ -183,8 +186,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private MagnificationController mMagnificationController;
private boolean mUnregisterMagnificationOnReset;
private InteractionBridge mInteractionBridge;
private AlertDialog mEnableTouchExplorationDialog;
@@ -784,11 +785,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
float scale, float centerX, float centerY) {
synchronized (mLock) {
notifyMagnificationChangedLocked(region, scale, centerX, centerY);
if (mUnregisterMagnificationOnReset && scale == 1.0f) {
mUnregisterMagnificationOnReset = false;
mMagnificationController.unregister();
}
}
}
@@ -1736,25 +1732,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
private void updateMagnificationLocked(UserState userState) {
final int userId = userState.mUserId;
if (userId == mCurrentUserId && mMagnificationController != null) {
if (userState.mIsDisplayMagnificationEnabled ||
userHasMagnificationServicesLocked(userState)) {
mMagnificationController.setUserId(userState.mUserId);
} else {
// If the user no longer has any magnification-controlling
// services and is not using magnification gestures, then
// reset the state to normal.
if (mMagnificationController.resetIfNeeded(true)) {
// Animations are still running, so wait until we receive a
// callback verifying that we've reset magnification.
mUnregisterMagnificationOnReset = true;
} else {
mUnregisterMagnificationOnReset = false;
mMagnificationController.unregister();
mMagnificationController = null;
}
}
if (userState.mUserId != mCurrentUserId) {
return;
}
if (userState.mIsDisplayMagnificationEnabled ||
userHasMagnificationServicesLocked(userState)) {
// Initialize the magnification controller if necessary
getMagnificationController();
mMagnificationController.register();
} else if (mMagnificationController != null) {
mMagnificationController.unregister();
}
}
@@ -2152,7 +2140,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
synchronized (mLock) {
if (mMagnificationController == null) {
mMagnificationController = new MagnificationController(mContext, this, mLock);
mMagnificationController.register();
mMagnificationController.setUserId(mCurrentUserId);
}
return mMagnificationController;
@@ -2886,7 +2873,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
final Region region = Region.obtain();
getMagnificationController().getMagnifiedRegion(region);
getMagnificationController().getMagnificationRegion(region);
return region;
} finally {
Binder.restoreCallingIdentity(identity);
@@ -2957,7 +2944,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
return getMagnificationController().setScaleAndCenter(
scale, centerX, centerY, animate);
scale, centerX, centerY, animate, mId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3090,10 +3077,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mInstalledServices.remove(mAccessibilityServiceInfo);
userState.mEnabledServices.remove(mComponentName);
userState.destroyUiAutomationService();
if (readConfigurationForUserStateLocked(userState)) {
onUserStateChangedLocked(userState);
}
}
if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) {
getMagnificationController().resetIfNeeded(true);
}
onUserStateChangedLocked(userState);
}
}

View File

@@ -17,6 +17,7 @@
package com.android.server.accessibility;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.server.LocalServices;
@@ -60,6 +61,8 @@ class MagnificationController {
private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
private static final int INVALID_ID = -1;
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
private static final float MIN_SCALE = 1.0f;
@@ -80,9 +83,8 @@ class MagnificationController {
*/
private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
private final Region mMagnifiedRegion = Region.obtain();
private final Region mAvailableRegion = Region.obtain();
private final Rect mMagnifiedBounds = new Rect();
private final Region mMagnificationRegion = Region.obtain();
private final Rect mMagnificationBounds = new Rect();
private final Rect mTempRect = new Rect();
private final Rect mTempRect1 = new Rect();
@@ -97,35 +99,67 @@ class MagnificationController {
private int mUserId;
private int mIdOfLastServiceToMagnify = INVALID_ID;
// Flag indicating that we are registered with window manager.
private boolean mRegistered;
private boolean mUnregisterPending;
public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
mAms = ams;
mContentResolver = context.getContentResolver();
mScreenStateObserver = new ScreenStateObserver(context, this);
mWindowStateObserver = new WindowStateObserver(context, this);
mSpecAnimationBridge = new SpecAnimationBridge(context);
mLock = lock;
mSpecAnimationBridge = new SpecAnimationBridge(context, mLock);
}
/**
* Registers magnification-related observers.
* Start tracking the magnification region for services that control magnification and the
* magnification gesture handler.
*
* This tracking imposes a cost on the system, so we avoid tracking this data
* unless it's required.
*/
public void register() {
mScreenStateObserver.register();
mWindowStateObserver.register();
// Obtain initial state.
mWindowStateObserver.getRegions(mMagnifiedRegion, mAvailableRegion);
mMagnifiedRegion.getBounds(mMagnifiedBounds);
synchronized (mLock) {
if (!mRegistered) {
mScreenStateObserver.register();
mWindowStateObserver.register();
mSpecAnimationBridge.setEnabled(true);
// Obtain initial state.
mWindowStateObserver.getMagnificationRegion(mMagnificationRegion);
mMagnificationRegion.getBounds(mMagnificationBounds);
mRegistered = true;
}
}
}
/**
* Unregisters magnification-related observers.
* Stop requiring tracking the magnification region. We may remain registered while we
* reset magnification.
*/
public void unregister() {
mSpecAnimationBridge.cancel();
synchronized (mLock) {
if (!isMagnifying()) {
unregisterInternalLocked();
} else {
mUnregisterPending = true;
resetLocked(true);
}
}
}
mScreenStateObserver.unregister();
mWindowStateObserver.unregister();
private void unregisterInternalLocked() {
if (mRegistered) {
mSpecAnimationBridge.setEnabled(false);
mScreenStateObserver.unregister();
mWindowStateObserver.unregister();
mMagnificationRegion.setEmpty();
mRegistered = false;
}
mUnregisterPending = false;
}
/**
@@ -137,24 +171,22 @@ class MagnificationController {
}
/**
* Sets the magnified and available regions.
* Update our copy of the current magnification region
*
* @param magnified the magnified region
* @param available the region available for magnification
* @param updateSpec {@code true} to update the scale and center based on
* the region bounds, {@code false} to leave them as-is
*/
private void setMagnifiedRegion(Region magnified, Region available, boolean updateSpec) {
private void onMagnificationRegionChanged(Region magnified, boolean updateSpec) {
synchronized (mLock) {
boolean magnificationChanged = false;
boolean boundsChanged = false;
if (!mMagnifiedRegion.equals(magnified)) {
mMagnifiedRegion.set(magnified);
mMagnifiedRegion.getBounds(mMagnifiedBounds);
if (!mMagnificationRegion.equals(magnified)) {
mMagnificationRegion.set(magnified);
mMagnificationRegion.getBounds(mMagnificationBounds);
boundsChanged = true;
}
mAvailableRegion.set(available);
if (updateSpec) {
final MagnificationSpec sentSpec = mSpecAnimationBridge.mSentMagnificationSpec;
final float scale = sentSpec.scale;
@@ -162,12 +194,12 @@ class MagnificationController {
final float offsetY = sentSpec.offsetY;
// Compute the new center and update spec as needed.
final float centerX = (mMagnifiedBounds.width() / 2.0f
+ mMagnifiedBounds.left - offsetX) / scale;
final float centerY = (mMagnifiedBounds.height() / 2.0f
+ mMagnifiedBounds.top - offsetY) / scale;
final float centerX = (mMagnificationBounds.width() / 2.0f
+ mMagnificationBounds.left - offsetX) / scale;
final float centerY = (mMagnificationBounds.height() / 2.0f
+ mMagnificationBounds.top - offsetY) / scale;
magnificationChanged = setScaleAndCenterLocked(
scale, centerX, centerY, false);
scale, centerX, centerY, false, INVALID_ID);
}
// If magnification changed we already notified for the change.
@@ -178,7 +210,7 @@ class MagnificationController {
}
/**
* Returns whether the magnified region contains the specified
* Returns whether the magnification region contains the specified
* screen-relative coordinates.
*
* @param x the screen-relative X coordinate to check
@@ -186,51 +218,36 @@ class MagnificationController {
* @return {@code true} if the coordinate is contained within the
* magnified region, or {@code false} otherwise
*/
public boolean magnifiedRegionContains(float x, float y) {
public boolean magnificationRegionContains(float x, float y) {
synchronized (mLock) {
return mMagnifiedRegion.contains((int) x, (int) y);
}
}
/**
* Returns whether the region available for magnification contains the
* specified screen-relative coordinates.
*
* @param x the screen-relative X coordinate to check
* @param y the screen-relative Y coordinate to check
* @return {@code true} if the coordinate is contained within the
* region available for magnification, or {@code false} otherwise
*/
private boolean availableRegionContains(float x, float y) {
synchronized (mLock) {
return mAvailableRegion.contains((int) x, (int) y);
return mMagnificationRegion.contains((int) x, (int) y);
}
}
/**
* Populates the specified rect with the screen-relative bounds of the
* magnified region. If magnification is not enabled, the returned
* magnification region. If magnification is not enabled, the returned
* bounds will be empty.
*
* @param outBounds rect to populate with the bounds of the magnified
* region
*/
public void getMagnifiedBounds(@NonNull Rect outBounds) {
public void getMagnificationBounds(@NonNull Rect outBounds) {
synchronized (mLock) {
outBounds.set(mMagnifiedBounds);
outBounds.set(mMagnificationBounds);
}
}
/**
* Populates the specified region with the screen-relative magnified
* Populates the specified region with the screen-relative magnification
* region. If magnification is not enabled, then the returned region
* will be empty.
*
* @param outRegion the region to populate
*/
public void getMagnifiedRegion(@NonNull Region outRegion) {
public void getMagnificationRegion(@NonNull Region outRegion) {
synchronized (mLock) {
outRegion.set(mMagnifiedRegion);
outRegion.set(mMagnificationRegion);
}
}
@@ -263,8 +280,8 @@ class MagnificationController {
*/
public float getCenterX() {
synchronized (mLock) {
return (mMagnifiedBounds.width() / 2.0f
+ mMagnifiedBounds.left - getOffsetX()) / getScale();
return (mMagnificationBounds.width() / 2.0f
+ mMagnificationBounds.left - getOffsetX()) / getScale();
}
}
@@ -286,8 +303,8 @@ class MagnificationController {
*/
public float getCenterY() {
synchronized (mLock) {
return (mMagnifiedBounds.height() / 2.0f
+ mMagnifiedBounds.top - getOffsetY()) / getScale();
return (mMagnificationBounds.height() / 2.0f
+ mMagnificationBounds.top - getOffsetY()) / getScale();
}
}
@@ -335,17 +352,25 @@ class MagnificationController {
*/
public boolean reset(boolean animate) {
synchronized (mLock) {
final MagnificationSpec spec = mCurrentMagnificationSpec;
final boolean changed = !spec.isNop();
if (changed) {
spec.clear();
onMagnificationChangedLocked();
}
mSpecAnimationBridge.updateSentSpec(spec, animate);
return changed;
return resetLocked(animate);
}
}
private boolean resetLocked(boolean animate) {
if (!mRegistered) {
return false;
}
final MagnificationSpec spec = mCurrentMagnificationSpec;
final boolean changed = !spec.isNop();
if (changed) {
spec.clear();
onMagnificationChangedLocked();
}
mIdOfLastServiceToMagnify = INVALID_ID;
mSpecAnimationBridge.updateSentSpec(spec, animate);
return changed;
}
/**
* Scales the magnified region around the specified pivot point,
* optionally animating the transition. If animation is disabled, the
@@ -356,16 +381,20 @@ class MagnificationController {
* @param pivotY the screen-relative Y coordinate around which to scale
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean setScale(float scale, float pivotX, float pivotY, boolean animate) {
public boolean setScale(float scale, float pivotX, float pivotY, boolean animate, int id) {
synchronized (mLock) {
if (!mRegistered) {
return false;
}
// Constrain scale immediately for use in the pivot calculations.
scale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
final Rect viewport = mTempRect;
mMagnifiedRegion.getBounds(viewport);
mMagnificationRegion.getBounds(viewport);
final MagnificationSpec spec = mCurrentMagnificationSpec;
final float oldScale = spec.scale;
final float oldCenterX = (viewport.width() / 2.0f - spec.offsetX) / oldScale;
@@ -376,7 +405,8 @@ class MagnificationController {
final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
final float centerX = normPivotX + offsetX;
final float centerY = normPivotY + offsetY;
return setScaleAndCenterLocked(scale, centerX, centerY, animate);
mIdOfLastServiceToMagnify = id;
return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
}
}
@@ -390,12 +420,16 @@ class MagnificationController {
* center
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean setCenter(float centerX, float centerY, boolean animate) {
public boolean setCenter(float centerX, float centerY, boolean animate, int id) {
synchronized (mLock) {
return setScaleAndCenterLocked(Float.NaN, centerX, centerY, animate);
if (!mRegistered) {
return false;
}
return setScaleAndCenterLocked(Float.NaN, centerX, centerY, animate, id);
}
}
@@ -411,19 +445,27 @@ class MagnificationController {
* center and scale, or {@link Float#NaN} to leave unchanged
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
public boolean setScaleAndCenter(float scale, float centerX, float centerY, boolean animate) {
public boolean setScaleAndCenter(
float scale, float centerX, float centerY, boolean animate, int id) {
synchronized (mLock) {
return setScaleAndCenterLocked(scale, centerX, centerY, animate);
if (!mRegistered) {
return false;
}
return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
}
}
private boolean setScaleAndCenterLocked(float scale, float centerX, float centerY,
boolean animate) {
boolean animate, int id) {
final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
mSpecAnimationBridge.updateSentSpec(mCurrentMagnificationSpec, animate);
if (isMagnifying() && (id != INVALID_ID)) {
mIdOfLastServiceToMagnify = id;
}
return changed;
}
@@ -432,22 +474,42 @@ class MagnificationController {
*
* @param offsetX the amount in pixels to offset the X center
* @param offsetY the amount in pixels to offset the Y center
* @param id the ID of the service requesting the change
*/
public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) {
public void offsetMagnifiedRegionCenter(float offsetX, float offsetY, int id) {
synchronized (mLock) {
if (!mRegistered) {
return;
}
final MagnificationSpec currSpec = mCurrentMagnificationSpec;
final float nonNormOffsetX = currSpec.offsetX - offsetX;
currSpec.offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
final float nonNormOffsetY = currSpec.offsetY - offsetY;
currSpec.offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
if (id != INVALID_ID) {
mIdOfLastServiceToMagnify = id;
}
mSpecAnimationBridge.updateSentSpec(currSpec, false);
}
}
/**
* Get the ID of the last service that changed the magnification spec.
*
* @return The id
*/
public int getIdOfLastServiceToMagnify() {
return mIdOfLastServiceToMagnify;
}
private void onMagnificationChangedLocked() {
mAms.onMagnificationStateChanged();
mAms.notifyMagnificationChanged(mMagnifiedRegion,
mAms.notifyMagnificationChanged(mMagnificationRegion,
getScale(), getCenterX(), getCenterY());
if (mUnregisterPending && !isMagnifying()) {
unregisterInternalLocked();
}
}
/**
@@ -503,8 +565,8 @@ class MagnificationController {
scale = getScale();
}
// Ensure requested center is within the available region.
if (!availableRegionContains(centerX, centerY)) {
// Ensure requested center is within the magnification region.
if (!magnificationRegionContains(centerX, centerY)) {
return false;
}
@@ -518,16 +580,16 @@ class MagnificationController {
changed = true;
}
final float nonNormOffsetX = mMagnifiedBounds.width() / 2.0f
+ mMagnifiedBounds.left - centerX * scale;
final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f
+ mMagnificationBounds.left - centerX * scale;
final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
if (Float.compare(currSpec.offsetX, offsetX) != 0) {
currSpec.offsetX = offsetX;
changed = true;
}
final float nonNormOffsetY = mMagnifiedBounds.height() / 2.0f
+ mMagnifiedBounds.top - centerY * scale;
final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f
+ mMagnificationBounds.top - centerY * scale;
final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
if (Float.compare(currSpec.offsetY, offsetY) != 0) {
currSpec.offsetY = offsetY;
@@ -542,12 +604,12 @@ class MagnificationController {
}
private float getMinOffsetXLocked() {
final float viewportWidth = mMagnifiedBounds.width();
final float viewportWidth = mMagnificationBounds.width();
return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
}
private float getMinOffsetYLocked() {
final float viewportHeight = mMagnifiedBounds.height();
final float viewportHeight = mMagnificationBounds.height();
return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
}
@@ -595,7 +657,7 @@ class MagnificationController {
final float scale = getSentScale();
final float offsetX = getSentOffsetX();
final float offsetY = getSentOffsetY();
getMagnifiedBounds(outFrame);
getMagnificationBounds(outFrame);
outFrame.offset((int) -offsetX, (int) -offsetY);
outFrame.scale(1.0f / scale);
}
@@ -603,7 +665,7 @@ class MagnificationController {
private void requestRectangleOnScreen(int left, int top, int right, int bottom) {
synchronized (mLock) {
final Rect magnifiedFrame = mTempRect;
getMagnifiedBounds(magnifiedFrame);
getMagnificationBounds(magnifiedFrame);
if (!magnifiedFrame.intersects(left, top, right, bottom)) {
return;
}
@@ -640,7 +702,7 @@ class MagnificationController {
}
final float scale = getScale();
offsetMagnifiedRegionCenter(scrollX * scale, scrollY * scale);
offsetMagnifiedRegionCenter(scrollX * scale, scrollY * scale, INVALID_ID);
}
}
@@ -656,7 +718,7 @@ class MagnificationController {
/**
* The magnification spec that was sent to the window manager. This should
* only be accessed and modified on the main (e.g. animation) thread.
* only be accessed with the lock held.
*/
private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
@@ -667,8 +729,13 @@ class MagnificationController {
private final ValueAnimator mTransformationAnimator;
private final long mMainThreadId;
private final Object mLock;
private SpecAnimationBridge(Context context) {
@GuardedBy("mLock")
private boolean mEnabled = false;
private SpecAnimationBridge(Context context, Object lock) {
mLock = lock;
final Looper mainLooper = context.getMainLooper();
mMainThreadId = mainLooper.getThread().getId();
@@ -685,9 +752,19 @@ class MagnificationController {
mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
}
public void cancel() {
if (mTransformationAnimator != null && mTransformationAnimator.isRunning()) {
mTransformationAnimator.cancel();
/**
* Enabled means the bridge will accept input. When not enabled, the output of the animator
* will be ignored
*/
public void setEnabled(boolean enabled) {
synchronized (mLock) {
if (enabled != mEnabled) {
mEnabled = enabled;
if (!mEnabled) {
mSentMagnificationSpec.clear();
mWindowManager.setMagnificationSpec(mSentMagnificationSpec);
}
}
}
}
@@ -710,28 +787,32 @@ class MagnificationController {
}
// If the current and sent specs don't match, update the sent spec.
final boolean changed = !mSentMagnificationSpec.equals(spec);
if (changed) {
if (animate) {
animateMagnificationSpec(spec);
} else {
setMagnificationSpec(spec);
synchronized (mLock) {
final boolean changed = !mSentMagnificationSpec.equals(spec);
if (changed) {
if (animate) {
animateMagnificationSpecLocked(spec);
} else {
setMagnificationSpecLocked(spec);
}
}
}
}
private void animateMagnificationSpec(MagnificationSpec toSpec) {
private void animateMagnificationSpecLocked(MagnificationSpec toSpec) {
mTransformationAnimator.setObjectValues(mSentMagnificationSpec, toSpec);
mTransformationAnimator.start();
}
private void setMagnificationSpec(MagnificationSpec spec) {
if (DEBUG_SET_MAGNIFICATION_SPEC) {
Slog.i(LOG_TAG, "Sending: " + spec);
}
private void setMagnificationSpecLocked(MagnificationSpec spec) {
if (mEnabled) {
if (DEBUG_SET_MAGNIFICATION_SPEC) {
Slog.i(LOG_TAG, "Sending: " + spec);
}
mSentMagnificationSpec.setTo(spec);
mWindowManager.setMagnificationSpec(spec);
mSentMagnificationSpec.setTo(spec);
mWindowManager.setMagnificationSpec(spec);
}
}
private class UpdateHandler extends Handler {
@@ -759,12 +840,16 @@ class MagnificationController {
@Override
public MagnificationSpec get(SpecAnimationBridge object) {
return object.mSentMagnificationSpec;
synchronized (object.mLock) {
return object.mSentMagnificationSpec;
}
}
@Override
public void set(SpecAnimationBridge object, MagnificationSpec value) {
object.setMagnificationSpec(value);
synchronized (object.mLock) {
object.setMagnificationSpecLocked(value);
}
}
}
@@ -862,15 +947,14 @@ class MagnificationController {
}
@Override
public void onMagnifiedBoundsChanged(Region magnified, Region available) {
public void onMagnificationRegionChanged(Region magnificationRegion) {
final SomeArgs args = SomeArgs.obtain();
args.arg1 = Region.obtain(magnified);
args.arg2 = Region.obtain(available);
args.arg1 = Region.obtain(magnificationRegion);
mHandler.obtainMessage(MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
}
private void handleOnMagnifiedBoundsChanged(Region magnified, Region available) {
mController.setMagnifiedRegion(magnified, available, mSpecIsDirty);
private void handleOnMagnifiedBoundsChanged(Region magnificationRegion) {
mController.onMagnificationRegionChanged(magnificationRegion, mSpecIsDirty);
mSpecIsDirty = false;
}
@@ -911,8 +995,15 @@ class MagnificationController {
mController.resetIfNeeded(true);
}
public void getRegions(@NonNull Region outMagnified, @NonNull Region outAvailable) {
mWindowManager.getMagnificationRegions(outMagnified, outAvailable);
/**
* This method is used to get the magnification region in the tiny time slice between
* registering the callbacks and handling the message.
* TODO: Elimiante this extra path, perhaps by processing the message immediately
*
* @param outMagnificationRegion
*/
public void getMagnificationRegion(@NonNull Region outMagnificationRegion) {
mWindowManager.getMagnificationRegion(outMagnificationRegion);
}
private class CallbackHandler extends Handler {
@@ -926,10 +1017,8 @@ class MagnificationController {
case MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED: {
final SomeArgs args = (SomeArgs) message.obj;
final Region magnifiedBounds = (Region) args.arg1;
final Region availableBounds = (Region) args.arg2;
handleOnMagnifiedBoundsChanged(magnifiedBounds, availableBounds);
handleOnMagnifiedBoundsChanged(magnifiedBounds);
magnifiedBounds.recycle();
availableBounds.recycle();
} break;
case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
final SomeArgs args = (SomeArgs) message.obj;

View File

@@ -237,7 +237,7 @@ class MagnificationGestureHandler implements EventStreamTransformation {
final float eventX = event.getX();
final float eventY = event.getY();
if (mMagnificationController.isMagnifying()
&& mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
&& mMagnificationController.magnificationRegionContains(eventX, eventY)) {
final float scale = mMagnificationController.getScale();
final float scaledOffsetX = mMagnificationController.getOffsetX();
final float scaledOffsetY = mMagnificationController.getOffsetY();
@@ -381,7 +381,8 @@ class MagnificationGestureHandler implements EventStreamTransformation {
Slog.i(LOG_TAG, "Panned content by scrollX: " + distanceX
+ " scrollY: " + distanceY);
}
mMagnificationController.offsetMagnifiedRegionCenter(distanceX, distanceY);
mMagnificationController.offsetMagnifiedRegionCenter(distanceX, distanceY,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
return true;
}
@@ -421,7 +422,8 @@ class MagnificationGestureHandler implements EventStreamTransformation {
final float pivotX = detector.getFocusX();
final float pivotY = detector.getFocusY();
mMagnificationController.setScale(scale, pivotX, pivotY, false);
mMagnificationController.setScale(scale, pivotX, pivotY, false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
return true;
}
@@ -469,14 +471,14 @@ class MagnificationGestureHandler implements EventStreamTransformation {
}
final float eventX = event.getX();
final float eventY = event.getY();
if (mMagnificationController.magnifiedRegionContains(eventX, eventY)) {
if (mMagnificationController.magnificationRegionContains(eventX, eventY)) {
if (mLastMoveOutsideMagnifiedRegion) {
mLastMoveOutsideMagnifiedRegion = false;
mMagnificationController.setCenter(eventX,
eventY, true);
mMagnificationController.setCenter(eventX, eventY, true,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
} else {
mMagnificationController.setCenter(eventX,
eventY, false);
mMagnificationController.setCenter(eventX, eventY, false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
}
} else {
mLastMoveOutsideMagnifiedRegion = true;
@@ -571,7 +573,7 @@ class MagnificationGestureHandler implements EventStreamTransformation {
switch (action) {
case MotionEvent.ACTION_DOWN: {
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
if (!mMagnificationController.magnifiedRegionContains(
if (!mMagnificationController.magnificationRegionContains(
event.getX(), event.getY())) {
transitionToDelegatingStateAndClear();
return;
@@ -616,7 +618,7 @@ class MagnificationGestureHandler implements EventStreamTransformation {
return;
}
mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
if (!mMagnificationController.magnifiedRegionContains(
if (!mMagnificationController.magnificationRegionContains(
event.getX(), event.getY())) {
transitionToDelegatingStateAndClear();
return;
@@ -726,7 +728,8 @@ class MagnificationGestureHandler implements EventStreamTransformation {
if (!mMagnificationController.isMagnifying()) {
final float targetScale = mMagnificationController.getPersistedScale();
final float scale = MathUtils.constrain(targetScale, MIN_SCALE, MAX_SCALE);
mMagnificationController.setScaleAndCenter(scale, up.getX(), up.getY(), true);
mMagnificationController.setScaleAndCenter(scale, up.getX(), up.getY(), true,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
} else {
mMagnificationController.reset(true);
}
@@ -742,7 +745,8 @@ class MagnificationGestureHandler implements EventStreamTransformation {
final float targetScale = mMagnificationController.getPersistedScale();
final float scale = MathUtils.constrain(targetScale, MIN_SCALE, MAX_SCALE);
mMagnificationController.setScaleAndCenter(scale, down.getX(), down.getY(), true);
mMagnificationController.setScaleAndCenter(scale, down.getX(), down.getY(), true,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
transitionToState(STATE_VIEWPORT_DRAGGING);
}

View File

@@ -124,9 +124,9 @@ final class AccessibilityController {
}
}
public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
public void getMagnificationRegionLocked(Region outMagnificationRegion) {
if (mDisplayMagnifier != null) {
mDisplayMagnifier.getMagnificationRegionsLocked(outMagnified, outAvailable);
mDisplayMagnifier.getMagnificationRegionLocked(outMagnificationRegion);
}
}
@@ -400,8 +400,8 @@ final class AccessibilityController {
return spec;
}
public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
mMagnifedViewport.getBoundsLocked(outMagnified, outAvailable);
public void getMagnificationRegionLocked(Region outMagnificationRegion) {
mMagnifedViewport.getMagnificationRegionLocked(outMagnificationRegion);
}
public void destroyLocked() {
@@ -424,10 +424,8 @@ final class AccessibilityController {
private final Matrix mTempMatrix = new Matrix();
private final Region mMagnifiedBounds = new Region();
private final Region mAvailableBounds = new Region();
private final Region mOldMagnifiedBounds = new Region();
private final Region mOldAvailableBounds = new Region();
private final Region mMagnificationRegion = new Region();
private final Region mOldMagnificationRegion = new Region();
private final Path mCircularPath;
@@ -463,10 +461,8 @@ final class AccessibilityController {
recomputeBoundsLocked();
}
public void getBoundsLocked(@NonNull Region outMagnified,
@NonNull Region outAvailable) {
outMagnified.set(mMagnifiedBounds);
outAvailable.set(mAvailableBounds);
public void getMagnificationRegionLocked(@NonNull Region outMagnificationRegion) {
outMagnificationRegion.set(mMagnificationRegion);
}
public void updateMagnificationSpecLocked(MagnificationSpec spec) {
@@ -488,11 +484,12 @@ final class AccessibilityController {
final int screenWidth = mTempPoint.x;
final int screenHeight = mTempPoint.y;
mMagnifiedBounds.set(0, 0, 0, 0);
mAvailableBounds.set(0, 0, screenWidth, screenHeight);
mMagnificationRegion.set(0, 0, 0, 0);
final Region availableBounds = mTempRegion1;
availableBounds.set(0, 0, screenWidth, screenHeight);
if (mCircularPath != null) {
mAvailableBounds.setPath(mCircularPath, mAvailableBounds);
availableBounds.setPath(mCircularPath, availableBounds);
}
Region nonMagnifiedBounds = mTempRegion4;
@@ -526,21 +523,21 @@ final class AccessibilityController {
(int) windowFrame.right, (int) windowFrame.bottom);
// Only update new regions
Region portionOfWindowAlreadyAccountedFor = mTempRegion3;
portionOfWindowAlreadyAccountedFor.set(mMagnifiedBounds);
portionOfWindowAlreadyAccountedFor.set(mMagnificationRegion);
portionOfWindowAlreadyAccountedFor.op(nonMagnifiedBounds, Region.Op.UNION);
windowBounds.op(portionOfWindowAlreadyAccountedFor, Region.Op.DIFFERENCE);
if (mWindowManagerService.mPolicy.canMagnifyWindow(windowState.mAttrs.type)) {
mMagnifiedBounds.op(windowBounds, Region.Op.UNION);
mMagnifiedBounds.op(mAvailableBounds, Region.Op.INTERSECT);
mMagnificationRegion.op(windowBounds, Region.Op.UNION);
mMagnificationRegion.op(availableBounds, Region.Op.INTERSECT);
} else {
nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
mAvailableBounds.op(windowBounds, Region.Op.DIFFERENCE);
availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
}
// Update accounted bounds
Region accountedBounds = mTempRegion2;
accountedBounds.set(mMagnifiedBounds);
accountedBounds.set(mMagnificationRegion);
accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
@@ -556,43 +553,36 @@ final class AccessibilityController {
visibleWindows.clear();
mMagnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
mMagnificationRegion.op(mDrawBorderInset, mDrawBorderInset,
screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
Region.Op.INTERSECT);
final boolean magnifiedChanged = !mOldMagnifiedBounds.equals(mMagnifiedBounds);
final boolean availableChanged = !mOldAvailableBounds.equals(mAvailableBounds);
if (magnifiedChanged || availableChanged) {
if (magnifiedChanged) {
mWindow.setBounds(mMagnifiedBounds);
Rect dirtyRect = mTempRect1;
if (mFullRedrawNeeded) {
mFullRedrawNeeded = false;
dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
screenWidth - mDrawBorderInset,
screenHeight - mDrawBorderInset);
mWindow.invalidate(dirtyRect);
} else {
Region dirtyRegion = mTempRegion3;
dirtyRegion.set(mMagnifiedBounds);
dirtyRegion.op(mOldMagnifiedBounds, Region.Op.UNION);
dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
dirtyRegion.getBounds(dirtyRect);
mWindow.invalidate(dirtyRect);
}
mOldMagnifiedBounds.set(mMagnifiedBounds);
}
if (availableChanged) {
mOldAvailableBounds.set(mAvailableBounds);
final boolean magnifiedChanged =
!mOldMagnificationRegion.equals(mMagnificationRegion);
if (magnifiedChanged) {
mWindow.setBounds(mMagnificationRegion);
final Rect dirtyRect = mTempRect1;
if (mFullRedrawNeeded) {
mFullRedrawNeeded = false;
dirtyRect.set(mDrawBorderInset, mDrawBorderInset,
screenWidth - mDrawBorderInset,
screenHeight - mDrawBorderInset);
mWindow.invalidate(dirtyRect);
} else {
final Region dirtyRegion = mTempRegion3;
dirtyRegion.set(mMagnificationRegion);
dirtyRegion.op(mOldMagnificationRegion, Region.Op.UNION);
dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
dirtyRegion.getBounds(dirtyRect);
mWindow.invalidate(dirtyRect);
}
mOldMagnificationRegion.set(mMagnificationRegion);
final SomeArgs args = SomeArgs.obtain();
args.arg1 = Region.obtain(mMagnifiedBounds);
args.arg2 = Region.obtain(mAvailableBounds);
args.arg1 = Region.obtain(mMagnificationRegion);
mHandler.obtainMessage(
MyHandler.MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
MyHandler.MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED, args)
.sendToTarget();
}
}
@@ -616,14 +606,14 @@ final class AccessibilityController {
public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
if (shown) {
mFullRedrawNeeded = true;
mOldMagnifiedBounds.set(0, 0, 0, 0);
mOldMagnificationRegion.set(0, 0, 0, 0);
}
mWindow.setShown(shown, animate);
}
public void getMagnifiedFrameInContentCoordsLocked(Rect rect) {
MagnificationSpec spec = mMagnificationSpec;
mMagnifiedBounds.getBounds(rect);
mMagnificationRegion.getBounds(rect);
rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
rect.scale(1.0f / spec.scale);
}
@@ -886,7 +876,7 @@ final class AccessibilityController {
}
private class MyHandler extends Handler {
public static final int MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED = 1;
public static final int MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED = 1;
public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
@@ -899,13 +889,11 @@ final class AccessibilityController {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED: {
case MESSAGE_NOTIFY_MAGNIFICATION_REGION_CHANGED: {
final SomeArgs args = (SomeArgs) message.obj;
final Region magnifiedBounds = (Region) args.arg1;
final Region availableBounds = (Region) args.arg2;
mCallbacks.onMagnifiedBoundsChanged(magnifiedBounds, availableBounds);
mCallbacks.onMagnificationRegionChanged(magnifiedBounds);
magnifiedBounds.recycle();
availableBounds.recycle();
} break;
case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {

View File

@@ -10975,12 +10975,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
public void getMagnificationRegions(@NonNull Region outMagnified,
@NonNull Region outAvailable) {
public void getMagnificationRegion(@NonNull Region magnificationRegion) {
synchronized (mWindowMap) {
if (mAccessibilityController != null) {
mAccessibilityController.getMagnificationRegionsLocked(
outMagnified, outAvailable);
mAccessibilityController.getMagnificationRegionLocked(magnificationRegion);
} else {
throw new IllegalStateException("Magnification callbacks not set!");
}