Merge "Various fixes for MagnificationController" into nyc-dev
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index c22d60d..3ad730b 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -157,6 +158,15 @@
     public abstract void setMagnificationSpec(MagnificationSpec spec);
 
     /**
+     * Obtains the magnified and available regions.
+     *
+     * @param outMagnified the currently magnified region
+     * @param outAvailable the region available for magnification
+     */
+    public abstract void getMagnificationRegions(@NonNull Region outMagnified,
+            @NonNull Region outAvailable);
+
+    /**
      * Gets the magnification and translation applied to a window given its token.
      * Not all windows are magnified and the window manager policy determines which
      * windows are magnified. The returned result also takes into account the compat
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index a093d92..e15b785 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -111,12 +111,18 @@
     public void register() {
         mScreenStateObserver.register();
         mWindowStateObserver.register();
+
+        // Obtain initial state.
+        mWindowStateObserver.getRegions(mMagnifiedRegion, mAvailableRegion);
+        mMagnifiedRegion.getBounds(mMagnifiedBounds);
     }
 
     /**
      * Unregisters magnification-related observers.
      */
     public void unregister() {
+        mSpecAnimationBridge.cancel();
+
         mScreenStateObserver.unregister();
         mWindowStateObserver.unregister();
     }
@@ -149,8 +155,10 @@
             final float offsetY = sentSpec.offsetY;
 
             // Compute the new center and update spec as needed.
-            final float centerX = (mMagnifiedBounds.width() / 2.0f - offsetX) / scale;
-            final float centerY = (mMagnifiedBounds.height() / 2.0f - offsetY) / scale;
+            final float centerX = (mMagnifiedBounds.width() / 2.0f
+                    + mMagnifiedBounds.left - offsetX) / scale;
+            final float centerY = (mMagnifiedBounds.height() / 2.0f
+                    + mMagnifiedBounds.top - offsetY) / scale;
             if (updateSpec) {
                 setScaleAndCenter(scale, centerX, centerY, false);
             } else {
@@ -246,7 +254,8 @@
      */
     public float getCenterX() {
         synchronized (mLock) {
-            return  (mMagnifiedBounds.width() / 2.0f - getOffsetX()) / getScale();
+            return  (mMagnifiedBounds.width() / 2.0f
+                    + mMagnifiedBounds.left - getOffsetX()) / getScale();
         }
     }
 
@@ -268,7 +277,8 @@
      */
     public float getCenterY() {
         synchronized (mLock) {
-            return (mMagnifiedBounds.height() / 2.0f - getOffsetY()) / getScale();
+            return (mMagnifiedBounds.height() / 2.0f
+                    + mMagnifiedBounds.top - getOffsetY()) / getScale();
         }
     }
 
@@ -471,18 +481,25 @@
      *         otherwise
      */
     private boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
+        // Handle defaults.
+        if (Float.isNaN(centerX)) {
+            centerX = getCenterX();
+        }
+        if (Float.isNaN(centerY)) {
+            centerY = getCenterY();
+        }
+        if (Float.isNaN(scale)) {
+            scale = getScale();
+        }
+
+        // Ensure requested center is within the available region.
         if (!availableRegionContains(centerX, centerY)) {
             return false;
         }
 
-        boolean changed = false;
-
+        // Compute changes.
         final MagnificationSpec currSpec = mCurrentMagnificationSpec;
-
-        // Handle scale.
-        if (Float.isNaN(scale)) {
-            scale = getScale();
-        }
+        boolean changed = false;
 
         final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
         if (Float.compare(currSpec.scale, normScale) != 0) {
@@ -490,24 +507,16 @@
             changed = true;
         }
 
-        // Handle X offset.
-        if (Float.isNaN(centerX)) {
-            centerX = getCenterX();
-        }
-
-        final float nonNormOffsetX = mMagnifiedBounds.width() / 2.0f - centerX * scale;
+        final float nonNormOffsetX = mMagnifiedBounds.width() / 2.0f
+                + mMagnifiedBounds.left - centerX * scale;
         final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
         if (Float.compare(currSpec.offsetX, offsetX) != 0) {
             currSpec.offsetX = offsetX;
             changed = true;
         }
 
-        // Handle Y offset.
-        if (Float.isNaN(centerY)) {
-            centerY = getCenterY();
-        }
-
-        final float nonNormOffsetY = mMagnifiedBounds.height() / 2.0f - centerY * scale;
+        final float nonNormOffsetY = mMagnifiedBounds.height() / 2.0f
+                + mMagnifiedBounds.top - centerY * scale;
         final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
         if (Float.compare(currSpec.offsetY, offsetY) != 0) {
             currSpec.offsetY = offsetY;
@@ -661,6 +670,12 @@
             mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
         }
 
+        public void cancel() {
+            if (mTransformationAnimator != null && mTransformationAnimator.isRunning()) {
+                mTransformationAnimator.cancel();
+            }
+        }
+
         public void updateSentSpec(MagnificationSpec spec, boolean animate) {
             if (Thread.currentThread().getId() == mMainThreadId) {
                 // Already on the main thread, don't bother proxying.
@@ -811,9 +826,6 @@
         private static final int MESSAGE_ON_USER_CONTEXT_CHANGED = 3;
         private static final int MESSAGE_ON_ROTATION_CHANGED = 4;
 
-        private final Rect mTempRect = new Rect();
-        private final Rect mTempRect1 = new Rect();
-
         private final MagnificationController mController;
         private final WindowManagerInternal mWindowManager;
         private final Handler mHandler;
@@ -884,6 +896,10 @@
             mController.resetIfNeeded(true);
         }
 
+        public void getRegions(@NonNull Region outMagnified, @NonNull Region outAvailable) {
+            mWindowManager.getMagnificationRegions(outMagnified, outAvailable);
+        }
+
         private class CallbackHandler extends Handler {
             public CallbackHandler(Context context) {
                 super(context.getMainLooper());
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 2c15818..98d44ac 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -21,6 +21,7 @@
 
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -122,6 +123,12 @@
         }
     }
 
+    public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
+        if (mDisplayMagnifier != null) {
+            mDisplayMagnifier.getMagnificationRegionsLocked(outMagnified, outAvailable);
+        }
+    }
+
     public void onRectangleOnScreenRequestedLocked(Rect rectangle) {
         if (mDisplayMagnifier != null) {
             mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
@@ -392,6 +399,10 @@
             return spec;
         }
 
+        public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
+            mMagnifedViewport.getBoundsLocked(outMagnified, outAvailable);
+        }
+
         public void destroyLocked() {
             mMagnifedViewport.destroyWindow();
         }
@@ -413,6 +424,7 @@
             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();
 
@@ -450,6 +462,12 @@
                 recomputeBoundsLocked();
             }
 
+            public void getBoundsLocked(@NonNull Region outMagnified,
+                    @NonNull Region outAvailable) {
+                outMagnified.set(mMagnifiedBounds);
+                outAvailable.set(mAvailableBounds);
+            }
+
             public void updateMagnificationSpecLocked(MagnificationSpec spec) {
                 if (spec != null) {
                     mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY);
@@ -469,14 +487,11 @@
                 final int screenWidth = mTempPoint.x;
                 final int screenHeight = mTempPoint.y;
 
-                Region magnifiedBounds = mMagnifiedBounds;
-                magnifiedBounds.set(0, 0, 0, 0);
-
-                Region availableBounds = mTempRegion1;
-                availableBounds.set(0, 0, screenWidth, screenHeight);
+                mMagnifiedBounds.set(0, 0, 0, 0);
+                mAvailableBounds.set(0, 0, screenWidth, screenHeight);
 
                 if (mCircularPath != null) {
-                    availableBounds.setPath(mCircularPath, availableBounds);
+                    mAvailableBounds.setPath(mCircularPath, mAvailableBounds);
                 }
 
                 Region nonMagnifiedBounds = mTempRegion4;
@@ -505,8 +520,8 @@
                         matrix.mapRect(windowFrame);
                         windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
                                 (int) windowFrame.right, (int) windowFrame.bottom);
-                        magnifiedBounds.op(windowBounds, Region.Op.UNION);
-                        magnifiedBounds.op(availableBounds, Region.Op.INTERSECT);
+                        mMagnifiedBounds.op(windowBounds, Region.Op.UNION);
+                        mMagnifiedBounds.op(mAvailableBounds, Region.Op.INTERSECT);
                     } else {
                         Region touchableRegion = mTempRegion3;
                         windowState.getTouchableRegion(touchableRegion);
@@ -518,12 +533,12 @@
                         windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
                                 (int) windowFrame.right, (int) windowFrame.bottom);
                         nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
-                        windowBounds.op(magnifiedBounds, Region.Op.DIFFERENCE);
-                        availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
+                        windowBounds.op(mMagnifiedBounds, Region.Op.DIFFERENCE);
+                        mAvailableBounds.op(windowBounds, Region.Op.DIFFERENCE);
                     }
 
                     Region accountedBounds = mTempRegion2;
-                    accountedBounds.set(magnifiedBounds);
+                    accountedBounds.set(mMagnifiedBounds);
                     accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
                     accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
 
@@ -539,15 +554,15 @@
 
                 visibleWindows.clear();
 
-                magnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
+                mMagnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
                         screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
                         Region.Op.INTERSECT);
 
-                final boolean magnifiedChanged = !mOldMagnifiedBounds.equals(magnifiedBounds);
-                final boolean availableChanged = !mOldAvailableBounds.equals(availableBounds);
+                final boolean magnifiedChanged = !mOldMagnifiedBounds.equals(mMagnifiedBounds);
+                final boolean availableChanged = !mOldAvailableBounds.equals(mAvailableBounds);
                 if (magnifiedChanged || availableChanged) {
                     if (magnifiedChanged) {
-                        mWindow.setBounds(magnifiedBounds);
+                        mWindow.setBounds(mMagnifiedBounds);
                         Rect dirtyRect = mTempRect1;
                         if (mFullRedrawNeeded) {
                             mFullRedrawNeeded = false;
@@ -557,23 +572,23 @@
                             mWindow.invalidate(dirtyRect);
                         } else {
                             Region dirtyRegion = mTempRegion3;
-                            dirtyRegion.set(magnifiedBounds);
+                            dirtyRegion.set(mMagnifiedBounds);
                             dirtyRegion.op(mOldMagnifiedBounds, Region.Op.UNION);
                             dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
                             dirtyRegion.getBounds(dirtyRect);
                             mWindow.invalidate(dirtyRect);
                         }
 
-                        mOldMagnifiedBounds.set(magnifiedBounds);
+                        mOldMagnifiedBounds.set(mMagnifiedBounds);
                     }
 
                     if (availableChanged) {
-                        mOldAvailableBounds.set(availableBounds);
+                        mOldAvailableBounds.set(mAvailableBounds);
                     }
 
                     final SomeArgs args = SomeArgs.obtain();
-                    args.arg1 = Region.obtain(magnifiedBounds);
-                    args.arg2 = Region.obtain(availableBounds);
+                    args.arg1 = Region.obtain(mMagnifiedBounds);
+                    args.arg2 = Region.obtain(mAvailableBounds);
                     mHandler.obtainMessage(
                             MyHandler.MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5771d69..5d13b3b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -10725,6 +10725,19 @@
         }
 
         @Override
+        public void getMagnificationRegions(@NonNull Region outMagnified,
+                @NonNull Region outAvailable) {
+            synchronized (mWindowMap) {
+                if (mAccessibilityController != null) {
+                    mAccessibilityController.getMagnificationRegionsLocked(
+                            outMagnified, outAvailable);
+                } else {
+                    throw new IllegalStateException("Magnification callbacks not set!");
+                }
+            }
+        }
+
+        @Override
         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
             synchronized (mWindowMap) {
                 WindowState windowState = mWindowMap.get(windowToken);