diff options
| author | 2015-11-02 18:46:48 +0000 | |
|---|---|---|
| committer | 2015-11-02 18:46:48 +0000 | |
| commit | 978db40983bd4ba2a9cb3502fd7c82c6f6311d64 (patch) | |
| tree | 7a1bad70fef3841bea8816e98a0e499c9d0357ca | |
| parent | 723b5d90df6a1acbb56bf8fc6c93e58ff105e599 (diff) | |
| parent | 57525a7054f16c198f463b1cf27988243bb96248 (diff) | |
Merge "Refactor MagnificationController out to its own class"
3 files changed, 393 insertions, 220 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 749a0807151a..535a8efc496b 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -91,7 +91,6 @@ import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.R; import com.android.internal.content.PackageMonitor; import com.android.internal.statusbar.IStatusBarService; -import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import org.xmlpull.v1.XmlPullParserException; @@ -180,6 +179,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final MainHandler mMainHandler; + private MagnificationController mMagnificationController; + private InteractionBridge mInteractionBridge; private AlertDialog mEnableTouchExplorationDialog; @@ -1936,6 +1937,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + MagnificationController getMagnificationController() { + if (mMagnificationController == null) { + mMagnificationController = new MagnificationController(mContext, this); + } + return mMagnificationController; + } + /** * This class represents an accessibility service. It stores all per service * data required for the service management, provides API for starting/stopping the diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java new file mode 100644 index 000000000000..b4411cf28487 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2015 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; + +import com.android.internal.R; +import com.android.server.LocalServices; + +import android.animation.ObjectAnimator; +import android.animation.TypeEvaluator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Rect; +import android.graphics.Region; +import android.util.Property; +import android.util.Slog; +import android.view.MagnificationSpec; +import android.view.WindowManagerInternal; +import android.view.animation.DecelerateInterpolator; + +/** + * This class is used to control and query the state of display magnification + * from the accessibility manager and related classes. It is responsible for + * holding the current state of magnification and animation, and it handles + * communication between the accessibility manager and window manager. + */ +class MagnificationController { + private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName(); + + private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false; + private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false; + + private static final String PROPERTY_NAME_MAGNIFICATION_SPEC = "magnificationSpec"; + + private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain(); + private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain(); + + private final Region mMagnifiedBounds = new Region(); + private final Rect mTempRect = new Rect(); + + private final AccessibilityManagerService mAms; + private final WindowManagerInternal mWindowManager; + private final ValueAnimator mTransformationAnimator; + + public MagnificationController(Context context, AccessibilityManagerService ams) { + mAms = ams; + mWindowManager = LocalServices.getService(WindowManagerInternal.class); + + final Property<MagnificationController, MagnificationSpec> property = + Property.of(MagnificationController.class, MagnificationSpec.class, + PROPERTY_NAME_MAGNIFICATION_SPEC); + final MagnificationSpecEvaluator evaluator = new MagnificationSpecEvaluator(); + final long animationDuration = context.getResources().getInteger( + R.integer.config_longAnimTime); + mTransformationAnimator = ObjectAnimator.ofObject(this, property, evaluator, + mSentMagnificationSpec, mCurrentMagnificationSpec); + mTransformationAnimator.setDuration(animationDuration); + mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f)); + } + + /** + * @return {@code true} if magnification is active, e.g. the scale + * is > 1, {@code false} otherwise + */ + public boolean isMagnifying() { + return mCurrentMagnificationSpec.scale > 1.0f; + } + + /** + * Sets the magnified region. + * + * @param region the region to set + * @param updateSpec {@code true} to update the scale and center based on + * the region bounds, {@code false} to leave them as-is + */ + public void setMagnifiedRegion(Region region, boolean updateSpec) { + mMagnifiedBounds.set(region); + + if (updateSpec) { + final Rect magnifiedFrame = mTempRect; + region.getBounds(magnifiedFrame); + final float scale = mSentMagnificationSpec.scale; + final float offsetX = mSentMagnificationSpec.offsetX; + final float offsetY = mSentMagnificationSpec.offsetY; + final float centerX = (-offsetX + magnifiedFrame.width() / 2) / scale; + final float centerY = (-offsetY + magnifiedFrame.height() / 2) / scale; + setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, false); + } else { + mAms.onMagnificationStateChanged(); + } + } + + /** + * Returns whether the magnified region 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 + * magnified region, or {@code false} otherwise + */ + public boolean magnifiedRegionContains(float x, float y) { + return mMagnifiedBounds.contains((int) x, (int) y); + } + + /** + * Populates the specified rect with the bounds of the magnified + * region. + * + * @param outBounds rect to populate with the bounds of the magnified + * region + */ + public void getMagnifiedBounds(Rect outBounds) { + mMagnifiedBounds.getBounds(outBounds); + } + + /** + * Returns the magnification scale. If an animation is in progress, + * this reflects the end state of the animation. + * + * @return the scale + */ + public float getScale() { + return mCurrentMagnificationSpec.scale; + } + + /** + * Returns the X offset of the magnification viewport. If an animation + * is in progress, this reflects the end state of the animation. + * + * @return the X offset + */ + public float getOffsetX() { + return mCurrentMagnificationSpec.offsetX; + } + + /** + * Returns the Y offset of the magnification viewport. If an animation + * is in progress, this reflects the end state of the animation. + * + * @return the Y offset + */ + public float getOffsetY() { + return mCurrentMagnificationSpec.offsetY; + } + + /** + * Returns the scale currently used by the window manager. If an + * animation is in progress, this reflects the current state of the + * animation. + * + * @return the scale currently used by the window manager + */ + public float getSentScale() { + return mSentMagnificationSpec.scale; + } + + /** + * Returns the X offset currently used by the window manager. If an + * animation is in progress, this reflects the current state of the + * animation. + * + * @return the X offset currently used by the window manager + */ + public float getSentOffsetX() { + return mSentMagnificationSpec.offsetX; + } + + /** + * Returns the Y offset currently used by the window manager. If an + * animation is in progress, this reflects the current state of the + * animation. + * + * @return the Y offset currently used by the window manager + */ + public float getSentOffsetY() { + return mSentMagnificationSpec.offsetY; + } + + /** + * Resets the magnification scale and center, optionally animating the + * transition. + * + * @param animate {@code true} to animate the transition, {@code false} + * to transition immediately + */ + public void reset(boolean animate) { + if (mTransformationAnimator.isRunning()) { + mTransformationAnimator.cancel(); + } + mCurrentMagnificationSpec.clear(); + if (animate) { + animateMagnificationSpec(mSentMagnificationSpec, + mCurrentMagnificationSpec); + } else { + setMagnificationSpec(mCurrentMagnificationSpec); + } + final Rect bounds = mTempRect; + bounds.setEmpty(); + mAms.onMagnificationStateChanged(); + } + + /** + * Scales the magnified region around the specified pivot point, + * optionally animating the transition. If animation is disabled, the + * transition is immediate. + * + * @param scale the target scale, must be >= 1 + * @param animate {@code true} to animate the transition, {@code false} + * to transition immediately + */ + public void setScale(float scale, float pivotX, float pivotY, boolean animate) { + final Rect magnifiedFrame = mTempRect; + mMagnifiedBounds.getBounds(magnifiedFrame); + final MagnificationSpec spec = mCurrentMagnificationSpec; + final float oldScale = spec.scale; + final float oldCenterX = (-spec.offsetX + magnifiedFrame.width() / 2) / oldScale; + final float oldCenterY = (-spec.offsetY + magnifiedFrame.height() / 2) / oldScale; + final float normPivotX = (-spec.offsetX + pivotX) / oldScale; + final float normPivotY = (-spec.offsetY + pivotY) / oldScale; + final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale); + final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale); + final float centerX = normPivotX + offsetX; + final float centerY = normPivotY + offsetY; + setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, animate); + } + + /** + * Sets the center of the magnified region, optionally animating the + * transition. If animation is disabled, the transition is immediate. + * + * @param centerX the screen-relative X coordinate around which to + * center + * @param centerY the screen-relative Y coordinate around which to + * center + * @param animate {@code true} to animate the transition, {@code false} + * to transition immediately + */ + public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) { + setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.scale, centerX, centerY, + animate); + } + + /** + * Sets the scale and center of the magnified region, optionally + * animating the transition. If animation is disabled, the transition + * is immediate. + * + * @param scale the target scale, must be >= 1 + * @param centerX the screen-relative X coordinate around which to + * center and scale + * @param centerY the screen-relative Y coordinate around which to + * center and scale + * @param animate {@code true} to animate the transition, {@code false} + * to transition immediately + */ + public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY, + boolean animate) { + if (Float.compare(mCurrentMagnificationSpec.scale, scale) == 0 + && Float.compare(mCurrentMagnificationSpec.offsetX, centerX) == 0 + && Float.compare(mCurrentMagnificationSpec.offsetY, centerY) == 0) { + return; + } + if (mTransformationAnimator.isRunning()) { + mTransformationAnimator.cancel(); + } + if (DEBUG_MAGNIFICATION_CONTROLLER) { + Slog.i(LOG_TAG, "scale: " + scale + " offsetX: " + centerX + " offsetY: " + centerY); + } + updateMagnificationSpec(scale, centerX, centerY); + if (animate) { + animateMagnificationSpec(mSentMagnificationSpec, + mCurrentMagnificationSpec); + } else { + setMagnificationSpec(mCurrentMagnificationSpec); + } + mAms.onMagnificationStateChanged(); + } + + /** + * Offsets the center of the magnified region. + * + * @param offsetX the amount in pixels to offset the X center + * @param offsetY the amount in pixels to offset the Y center + */ + public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) { + final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX; + mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX, + getMinOffsetX()), 0); + final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY; + mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY, + getMinOffsetY()), 0); + setMagnificationSpec(mCurrentMagnificationSpec); + } + + private void updateMagnificationSpec(float scale, float magnifiedCenterX, + float magnifiedCenterY) { + final Rect magnifiedFrame = mTempRect; + mMagnifiedBounds.getBounds(magnifiedFrame); + mCurrentMagnificationSpec.scale = scale; + final int viewportWidth = magnifiedFrame.width(); + final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale; + mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX, + getMinOffsetX()), 0); + final int viewportHeight = magnifiedFrame.height(); + final float nonNormOffsetY = viewportHeight / 2 - magnifiedCenterY * scale; + mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY, + getMinOffsetY()), 0); + } + + private float getMinOffsetX() { + final Rect magnifiedFrame = mTempRect; + mMagnifiedBounds.getBounds(magnifiedFrame); + final float viewportWidth = magnifiedFrame.width(); + return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale; + } + + private float getMinOffsetY() { + final Rect magnifiedFrame = mTempRect; + mMagnifiedBounds.getBounds(magnifiedFrame); + final float viewportHeight = magnifiedFrame.height(); + return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale; + } + + private void animateMagnificationSpec(MagnificationSpec fromSpec, + MagnificationSpec toSpec) { + mTransformationAnimator.setObjectValues(fromSpec, toSpec); + mTransformationAnimator.start(); + } + + private void setMagnificationSpec(MagnificationSpec spec) { + if (DEBUG_SET_MAGNIFICATION_SPEC) { + Slog.i(LOG_TAG, "Sending: " + spec); + } + mSentMagnificationSpec.scale = spec.scale; + mSentMagnificationSpec.offsetX = spec.offsetX; + mSentMagnificationSpec.offsetY = spec.offsetY; + mWindowManager.setMagnificationSpec(MagnificationSpec.obtain(spec)); + } + + private static class MagnificationSpecEvaluator implements TypeEvaluator<MagnificationSpec> { + private final MagnificationSpec mTempTransformationSpec = MagnificationSpec.obtain(); + + @Override + public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec, + MagnificationSpec toSpec) { + final MagnificationSpec result = mTempTransformationSpec; + result.scale = fromSpec.scale + (toSpec.scale - fromSpec.scale) * fraction; + result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX) * fraction; + result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY) * fraction; + return result; + } + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java index 8845bc0246ba..8feb167f4c99 100644 --- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java +++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java @@ -16,9 +16,6 @@ package com.android.server.accessibility; -import android.animation.ObjectAnimator; -import android.animation.TypeEvaluator; -import android.animation.ValueAnimator; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -31,14 +28,12 @@ import android.os.Handler; import android.os.Message; import android.provider.Settings; import android.text.TextUtils; -import android.util.Property; import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.InputDevice; import android.view.KeyEvent; -import android.view.MagnificationSpec; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; @@ -48,7 +43,6 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManagerInternal; import android.view.accessibility.AccessibilityEvent; -import android.view.animation.DecelerateInterpolator; import com.android.internal.os.SomeArgs; import com.android.server.LocalServices; @@ -101,10 +95,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio private static final boolean DEBUG_STATE_TRANSITIONS = false; private static final boolean DEBUG_DETECTING = false; - private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false; private static final boolean DEBUG_PANNING = false; private static final boolean DEBUG_SCALING = false; - private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false; private static final int STATE_DELEGATING = 1; private static final int STATE_DETECTING = 2; @@ -134,8 +126,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler; private final StateViewportDraggingHandler mStateViewportDraggingHandler; - private final AccessibilityManagerService mAms; - private final int mUserId; private final int mTapTimeSlop = ViewConfiguration.getJumpTapTimeout(); @@ -143,10 +133,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio private final int mTapDistanceSlop; private final int mMultiTapDistanceSlop; - private final long mLongAnimationDuration; - - private final Region mMagnifiedBounds = new Region(); - private EventStreamTransformation mNext; private int mCurrentState; @@ -194,13 +180,10 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio mContext = context; mUserId = userId; mWindowManager = LocalServices.getService(WindowManagerInternal.class); - mAms = service; mMultiTapTimeSlop = ViewConfiguration.getDoubleTapTimeout() + mContext.getResources().getInteger( com.android.internal.R.integer.config_screen_magnification_multi_tap_adjustment); - mLongAnimationDuration = context.getResources().getInteger( - com.android.internal.R.integer.config_longAnimTime); mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mMultiTapDistanceSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); @@ -209,7 +192,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio mMagnifiedContentInteractonStateHandler = new MagnifiedContentInteractonStateHandler( context); - mMagnificationController = new MagnificationController(mLongAnimationDuration); + mMagnificationController = service.getMagnificationController(); mScreenStateObserver = new ScreenStateObserver(context, mMagnificationController); mWindowManager.setMagnificationCallbacks(this); @@ -230,19 +213,9 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio // If there was a rotation we have to update the center of the magnified // region since the old offset X/Y may be out of its acceptable range for // the new display width and height. - if (mUpdateMagnificationSpecOnNextBoundsChange) { - mUpdateMagnificationSpecOnNextBoundsChange = false; - MagnificationSpec spec = mMagnificationController.getMagnificationSpec(); - Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); - final float scale = spec.scale; - final float centerX = (-spec.offsetX + magnifiedFrame.width() / 2) / scale; - final float centerY = (-spec.offsetY + magnifiedFrame.height() / 2) / scale; - mMagnificationController.setScaleAndMagnifiedRegionCenter(scale, centerX, - centerY, false); - } - mMagnifiedBounds.set(bounds); - mAms.onMagnificationStateChanged(); + mMagnificationController.setMagnifiedRegion( + bounds, mUpdateMagnificationSpecOnNextBoundsChange); + mUpdateMagnificationSpecOnNextBoundsChange = false; } @Override @@ -257,7 +230,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio private void handleOnRectangleOnScreenRequested(int left, int top, int right, int bottom) { Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); + mMagnificationController.getMagnifiedBounds(magnifiedFrame); if (!magnifiedFrame.intersects(left, top, right, bottom)) { return; } @@ -314,10 +287,12 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio } private void getMagnifiedFrameInContentCoords(Rect rect) { - MagnificationSpec spec = mMagnificationController.getMagnificationSpec(); - mMagnifiedBounds.getBounds(rect); - rect.offset((int) -spec.offsetX, (int) -spec.offsetY); - rect.scale(1.0f / spec.scale); + final float scale = mMagnificationController.getSentScale(); + final float offsetX = mMagnificationController.getSentOffsetX(); + final float offsetY = mMagnificationController.getSentOffsetY(); + mMagnificationController.getMagnifiedBounds(rect); + rect.offset((int) -offsetX, (int) -offsetY); + rect.scale(1.0f / scale); } private void resetMagnificationIfNeeded() { @@ -421,7 +396,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio final float eventX = event.getX(); final float eventY = event.getY(); if (mMagnificationController.isMagnifying() - && mMagnifiedBounds.contains((int) eventX, (int) eventY)) { + && mMagnificationController.magnifiedRegionContains(eventX, eventY)) { final float scale = mMagnificationController.getScale(); final float scaledOffsetX = mMagnificationController.getOffsetX(); final float scaledOffsetY = mMagnificationController.getOffsetY(); @@ -623,7 +598,7 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio } final float eventX = event.getX(); final float eventY = event.getY(); - if (mMagnifiedBounds.contains((int) eventX, (int) eventY)) { + if (mMagnificationController.magnifiedRegionContains(eventX, eventY)) { if (mLastMoveOutsideMagnifiedRegion) { mLastMoveOutsideMagnifiedRegion = false; mMagnificationController.setMagnifiedRegionCenter(eventX, @@ -696,8 +671,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio switch (action) { case MotionEvent.ACTION_DOWN: { mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - if (!mMagnifiedBounds.contains((int) event.getX(), - (int) event.getY())) { + if (!mMagnificationController.magnifiedRegionContains( + event.getX(), event.getY())) { transitionToDelegatingStateAndClear(); return; } @@ -738,7 +713,8 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio return; } mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD); - if (!mMagnifiedBounds.contains((int) event.getX(), (int) event.getY())) { + if (!mMagnificationController.magnifiedRegionContains( + event.getX(), event.getY())) { transitionToDelegatingStateAndClear(); return; } @@ -947,184 +923,6 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio } } - private final class MagnificationController { - - private static final String PROPERTY_NAME_MAGNIFICATION_SPEC = - "magnificationSpec"; - - private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain(); - - private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain(); - - private final Rect mTempRect = new Rect(); - - private final ValueAnimator mTransformationAnimator; - - public MagnificationController(long animationDuration) { - Property<MagnificationController, MagnificationSpec> property = - Property.of(MagnificationController.class, MagnificationSpec.class, - PROPERTY_NAME_MAGNIFICATION_SPEC); - TypeEvaluator<MagnificationSpec> evaluator = new TypeEvaluator<MagnificationSpec>() { - private final MagnificationSpec mTempTransformationSpec = - MagnificationSpec.obtain(); - @Override - public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec, - MagnificationSpec toSpec) { - MagnificationSpec result = mTempTransformationSpec; - result.scale = fromSpec.scale - + (toSpec.scale - fromSpec.scale) * fraction; - result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX) - * fraction; - result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY) - * fraction; - return result; - } - }; - mTransformationAnimator = ObjectAnimator.ofObject(this, property, - evaluator, mSentMagnificationSpec, mCurrentMagnificationSpec); - mTransformationAnimator.setDuration((long) (animationDuration)); - mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f)); - } - - public boolean isMagnifying() { - return mCurrentMagnificationSpec.scale > 1.0f; - } - - public void reset(boolean animate) { - if (mTransformationAnimator.isRunning()) { - mTransformationAnimator.cancel(); - } - mCurrentMagnificationSpec.clear(); - if (animate) { - animateMangificationSpec(mSentMagnificationSpec, - mCurrentMagnificationSpec); - } else { - setMagnificationSpec(mCurrentMagnificationSpec); - } - Rect bounds = mTempRect; - bounds.setEmpty(); - mAms.onMagnificationStateChanged(); - } - - public float getScale() { - return mCurrentMagnificationSpec.scale; - } - - public float getOffsetX() { - return mCurrentMagnificationSpec.offsetX; - } - - public float getOffsetY() { - return mCurrentMagnificationSpec.offsetY; - } - - public void setScale(float scale, float pivotX, float pivotY, boolean animate) { - Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); - MagnificationSpec spec = mCurrentMagnificationSpec; - final float oldScale = spec.scale; - final float oldCenterX = (-spec.offsetX + magnifiedFrame.width() / 2) / oldScale; - final float oldCenterY = (-spec.offsetY + magnifiedFrame.height() / 2) / oldScale; - final float normPivotX = (-spec.offsetX + pivotX) / oldScale; - final float normPivotY = (-spec.offsetY + pivotY) / oldScale; - final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale); - final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale); - final float centerX = normPivotX + offsetX; - final float centerY = normPivotY + offsetY; - setScaleAndMagnifiedRegionCenter(scale, centerX, centerY, animate); - } - - public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) { - setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.scale, centerX, centerY, - animate); - } - - public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) { - final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX; - mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX, - getMinOffsetX()), 0); - final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY; - mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY, - getMinOffsetY()), 0); - setMagnificationSpec(mCurrentMagnificationSpec); - } - - public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY, - boolean animate) { - if (Float.compare(mCurrentMagnificationSpec.scale, scale) == 0 - && Float.compare(mCurrentMagnificationSpec.offsetX, - centerX) == 0 - && Float.compare(mCurrentMagnificationSpec.offsetY, - centerY) == 0) { - return; - } - if (mTransformationAnimator.isRunning()) { - mTransformationAnimator.cancel(); - } - if (DEBUG_MAGNIFICATION_CONTROLLER) { - Slog.i(LOG_TAG, "scale: " + scale + " offsetX: " + centerX - + " offsetY: " + centerY); - } - updateMagnificationSpec(scale, centerX, centerY); - if (animate) { - animateMangificationSpec(mSentMagnificationSpec, - mCurrentMagnificationSpec); - } else { - setMagnificationSpec(mCurrentMagnificationSpec); - } - mAms.onMagnificationStateChanged(); - } - - public void updateMagnificationSpec(float scale, float magnifiedCenterX, - float magnifiedCenterY) { - Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); - mCurrentMagnificationSpec.scale = scale; - final int viewportWidth = magnifiedFrame.width(); - final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale; - mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX, - getMinOffsetX()), 0); - final int viewportHeight = magnifiedFrame.height(); - final float nonNormOffsetY = viewportHeight / 2 - magnifiedCenterY * scale; - mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY, - getMinOffsetY()), 0); - } - - private float getMinOffsetX() { - Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); - final float viewportWidth = magnifiedFrame.width(); - return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale; - } - - private float getMinOffsetY() { - Rect magnifiedFrame = mTempRect; - mMagnifiedBounds.getBounds(magnifiedFrame); - final float viewportHeight = magnifiedFrame.height(); - return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale; - } - - private void animateMangificationSpec(MagnificationSpec fromSpec, - MagnificationSpec toSpec) { - mTransformationAnimator.setObjectValues(fromSpec, toSpec); - mTransformationAnimator.start(); - } - - public MagnificationSpec getMagnificationSpec() { - return mSentMagnificationSpec; - } - - public void setMagnificationSpec(MagnificationSpec spec) { - if (DEBUG_SET_MAGNIFICATION_SPEC) { - Slog.i(LOG_TAG, "Sending: " + spec); - } - mSentMagnificationSpec.scale = spec.scale; - mSentMagnificationSpec.offsetX = spec.offsetX; - mSentMagnificationSpec.offsetY = spec.offsetY; - mWindowManager.setMagnificationSpec(MagnificationSpec.obtain(spec)); - } - } - private final class ScreenStateObserver extends BroadcastReceiver { private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1; |