/*
 * 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.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.server.LocalServices;

import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
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;
import android.view.MagnificationSpec;
import android.view.View;
import android.view.WindowManagerInternal;
import android.view.animation.DecelerateInterpolator;

import java.util.Locale;

/**
 * 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.
 *
 * Magnification is limited to the range [MIN_SCALE, MAX_SCALE], and can only occur inside the
 * magnification region. If a value is out of bounds, it will be adjusted to guarantee these
 * constraints.
 */
class MagnificationController implements Handler.Callback {
    private static final String LOG_TAG = "MagnificationController";

    public static final float MIN_SCALE = 1.0f;
    public static final float MAX_SCALE = 5.0f;

    private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;

    private static final int INVALID_ID = -1;

    private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;

    // Messages
    private static final int MSG_SEND_SPEC_TO_ANIMATION = 1;
    private static final int MSG_SCREEN_TURNED_OFF = 2;
    private static final int MSG_ON_MAGNIFIED_BOUNDS_CHANGED = 3;
    private static final int MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED = 4;
    private static final int MSG_ON_USER_CONTEXT_CHANGED = 5;

    private final Object mLock;

    /**
     * The current magnification spec. If an animation is running, this
     * reflects the end state.
     */
    private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();

    private final Region mMagnificationRegion = Region.obtain();
    private final Rect mMagnificationBounds = new Rect();

    private final Rect mTempRect = new Rect();
    private final Rect mTempRect1 = new Rect();

    private final AccessibilityManagerService mAms;

    private final SettingsBridge mSettingsBridge;

    private final ScreenStateObserver mScreenStateObserver;

    private final SpecAnimationBridge mSpecAnimationBridge;

    private final WindowManagerInternal.MagnificationCallbacks mWMCallbacks =
            new WindowManagerInternal.MagnificationCallbacks () {
                @Override
                public void onMagnificationRegionChanged(Region region) {
                    final SomeArgs args = SomeArgs.obtain();
                    args.arg1 = Region.obtain(region);
                    mHandler.obtainMessage(MSG_ON_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
                }

                @Override
                public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
                    final SomeArgs args = SomeArgs.obtain();
                    args.argi1 = left;
                    args.argi2 = top;
                    args.argi3 = right;
                    args.argi4 = bottom;
                    mHandler.obtainMessage(MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED, args)
                            .sendToTarget();
                }

                @Override
                public void onRotationChanged(int rotation) {
                    // Treat as context change and reset
                    mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
                }

                @Override
                public void onUserContextChanged() {
                    mHandler.sendEmptyMessage(MSG_ON_USER_CONTEXT_CHANGED);
                }
            };

    private int mUserId;

    private final long mMainThreadId;

    private Handler mHandler;

    private int mIdOfLastServiceToMagnify = INVALID_ID;

    private final WindowManagerInternal mWindowManager;

    // Flag indicating that we are registered with window manager.
    private boolean mRegistered;

    private boolean mUnregisterPending;

    public MagnificationController(Context context, AccessibilityManagerService ams, Object lock) {
        this(context, ams, lock, null, LocalServices.getService(WindowManagerInternal.class),
                new ValueAnimator(), new SettingsBridge(context.getContentResolver()));
        mHandler = new Handler(context.getMainLooper(), this);
    }

    public MagnificationController(Context context, AccessibilityManagerService ams, Object lock,
            Handler handler, WindowManagerInternal windowManagerInternal,
            ValueAnimator valueAnimator, SettingsBridge settingsBridge) {
        mHandler = handler;
        mWindowManager = windowManagerInternal;
        mMainThreadId = context.getMainLooper().getThread().getId();
        mAms = ams;
        mScreenStateObserver = new ScreenStateObserver(context, this);
        mLock = lock;
        mSpecAnimationBridge = new SpecAnimationBridge(
                context, mLock, mWindowManager, valueAnimator);
        mSettingsBridge = settingsBridge;
    }

    /**
     * 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() {
        synchronized (mLock) {
            if (!mRegistered) {
                mScreenStateObserver.register();
                mWindowManager.setMagnificationCallbacks(mWMCallbacks);
                mSpecAnimationBridge.setEnabled(true);
                // Obtain initial state.
                mWindowManager.getMagnificationRegion(mMagnificationRegion);
                mMagnificationRegion.getBounds(mMagnificationBounds);
                mRegistered = true;
            }
        }
    }

    /**
     * Stop requiring tracking the magnification region. We may remain registered while we
     * reset magnification.
     */
    public void unregister() {
        synchronized (mLock) {
            if (!isMagnifying()) {
                unregisterInternalLocked();
            } else {
                mUnregisterPending = true;
                resetLocked(true);
            }
        }
    }

    /**
     * Check if we are registered. Note that we may be planning to unregister at any moment.
     *
     * @return {@code true} if the controller is registered. {@code false} otherwise.
     */
    public boolean isRegisteredLocked() {
        return mRegistered;
    }

    private void unregisterInternalLocked() {
        if (mRegistered) {
            mSpecAnimationBridge.setEnabled(false);
            mScreenStateObserver.unregister();
            mWindowManager.setMagnificationCallbacks(null);
            mMagnificationRegion.setEmpty();
            mRegistered = false;
        }
        mUnregisterPending = false;
    }

    /**
     * @return {@code true} if magnification is active, e.g. the scale
     *         is > 1, {@code false} otherwise
     */
    public boolean isMagnifying() {
        return mCurrentMagnificationSpec.scale > 1.0f;
    }

    /**
     * Update our copy of the current magnification region
     *
     * @param magnified the magnified region
     */
    private void onMagnificationRegionChanged(Region magnified) {
        synchronized (mLock) {
            if (!mRegistered) {
                // Don't update if we've unregistered
                return;
            }
            if (!mMagnificationRegion.equals(magnified)) {
                mMagnificationRegion.set(magnified);
                mMagnificationRegion.getBounds(mMagnificationBounds);
                // It's possible that our magnification spec is invalid with the new bounds.
                // Adjust the current spec's offsets if necessary.
                if (updateCurrentSpecWithOffsetsLocked(
                        mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
                    sendSpecToAnimation(mCurrentMagnificationSpec, false);
                }
                onMagnificationChangedLocked();
            }
        }
    }

    /**
     * Returns whether the magnification 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 magnificationRegionContains(float x, float y) {
        synchronized (mLock) {
            return mMagnificationRegion.contains((int) x, (int) y);
        }
    }

    /**
     * Populates the specified rect with the screen-relative bounds of the
     * 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 getMagnificationBounds(@NonNull Rect outBounds) {
        synchronized (mLock) {
            outBounds.set(mMagnificationBounds);
        }
    }

    /**
     * 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 getMagnificationRegion(@NonNull Region outRegion) {
        synchronized (mLock) {
            outRegion.set(mMagnificationRegion);
        }
    }

    /**
     * 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 screen-relative X coordinate of the center of the
     * magnification viewport.
     *
     * @return the X coordinate
     */
    public float getCenterX() {
        synchronized (mLock) {
            return (mMagnificationBounds.width() / 2.0f
                    + mMagnificationBounds.left - getOffsetX()) / getScale();
        }
    }

    /**
     * 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 screen-relative Y coordinate of the center of the
     * magnification viewport.
     *
     * @return the Y coordinate
     */
    public float getCenterY() {
        synchronized (mLock) {
            return (mMagnificationBounds.height() / 2.0f
                    + mMagnificationBounds.top - getOffsetY()) / getScale();
        }
    }

    /**
     * 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
     */
    private float getSentScale() {
        return mSpecAnimationBridge.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
     */
    private float getSentOffsetX() {
        return mSpecAnimationBridge.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
     */
    private float getSentOffsetY() {
        return mSpecAnimationBridge.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
     * @return {@code true} if the magnification spec changed, {@code false} if
     *         the spec did not change
     */
    public boolean reset(boolean animate) {
        synchronized (mLock) {
            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;
        sendSpecToAnimation(spec, animate);
        return changed;
    }

    /**
     * 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 pivotX the screen-relative X coordinate around which to scale
     * @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, 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;
            mMagnificationRegion.getBounds(viewport);
            final MagnificationSpec spec = mCurrentMagnificationSpec;
            final float oldScale = spec.scale;
            final float oldCenterX = (viewport.width() / 2.0f - spec.offsetX) / oldScale;
            final float oldCenterY = (viewport.height() / 2.0f - spec.offsetY) / oldScale;
            final float normPivotX = (pivotX - spec.offsetX) / oldScale;
            final float normPivotY = (pivotY - spec.offsetY) / 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;
            mIdOfLastServiceToMagnify = id;
            return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
        }
    }

    /**
     * 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
     * @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, int id) {
        synchronized (mLock) {
            if (!mRegistered) {
                return false;
            }
            return setScaleAndCenterLocked(Float.NaN, centerX, centerY, animate, id);
        }
    }

    /**
     * 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, or {@link Float#NaN} to leave unchanged
     * @param centerX the screen-relative X coordinate around which to
     *                center and scale, or {@link Float#NaN} to leave unchanged
     * @param centerY the screen-relative Y coordinate around which to
     *                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, int id) {
        synchronized (mLock) {
            if (!mRegistered) {
                return false;
            }
            return setScaleAndCenterLocked(scale, centerX, centerY, animate, id);
        }
    }

    private boolean setScaleAndCenterLocked(float scale, float centerX, float centerY,
            boolean animate, int id) {
        final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
        sendSpecToAnimation(mCurrentMagnificationSpec, animate);
        if (isMagnifying() && (id != INVALID_ID)) {
            mIdOfLastServiceToMagnify = id;
        }
        return changed;
    }

    /**
     * Offsets the magnified region. Note that the offsetX and offsetY values actually move in the
     * opposite direction as the offsets passed in here.
     *
     * @param offsetX the amount in pixels to offset the region in the X direction, in current
     * screen pixels.
     * @param offsetY the amount in pixels to offset the region in the Y direction, in current
     * screen pixels.
     * @param id the ID of the service requesting the change
     */
    public void offsetMagnifiedRegion(float offsetX, float offsetY, int id) {
        synchronized (mLock) {
            if (!mRegistered) {
                return;
            }

            final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
            final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
            updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
            if (id != INVALID_ID) {
                mIdOfLastServiceToMagnify = id;
            }
            sendSpecToAnimation(mCurrentMagnificationSpec, 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.notifyMagnificationChanged(mMagnificationRegion,
                getScale(), getCenterX(), getCenterY());
        if (mUnregisterPending && !isMagnifying()) {
            unregisterInternalLocked();
        }
    }

    /**
     * Persists the current magnification scale to the current user's settings.
     */
    public void persistScale() {
        final float scale = mCurrentMagnificationSpec.scale;
        final int userId = mUserId;

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

    /**
     * Retrieves a previously persisted magnification scale from the current
     * user's settings.
     *
     * @return the previously persisted magnification scale, or the default
     *         scale if none is available
     */
    public float getPersistedScale() {
        return mSettingsBridge.getMagnificationScale(mUserId);
    }

    /**
     * Updates the current magnification spec.
     *
     * @param scale the magnification scale
     * @param centerX the unscaled, screen-relative X coordinate of the center
     *                of the viewport, or {@link Float#NaN} to leave unchanged
     * @param centerY the unscaled, screen-relative Y coordinate of the center
     *                of the viewport, or {@link Float#NaN} to leave unchanged
     * @return {@code true} if the magnification spec changed or {@code false}
     *         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();
        }

        // Compute changes.
        boolean changed = false;

        final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
        if (Float.compare(mCurrentMagnificationSpec.scale, normScale) != 0) {
            mCurrentMagnificationSpec.scale = normScale;
            changed = true;
        }

        final float nonNormOffsetX = mMagnificationBounds.width() / 2.0f
                + mMagnificationBounds.left - centerX * normScale;
        final float nonNormOffsetY = mMagnificationBounds.height() / 2.0f
                + mMagnificationBounds.top - centerY * normScale;
        changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);

        if (changed) {
            onMagnificationChangedLocked();
        }

        return changed;
    }

    private boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
        boolean changed = false;
        final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
        if (Float.compare(mCurrentMagnificationSpec.offsetX, offsetX) != 0) {
            mCurrentMagnificationSpec.offsetX = offsetX;
            changed = true;
        }
        final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
        if (Float.compare(mCurrentMagnificationSpec.offsetY, offsetY) != 0) {
            mCurrentMagnificationSpec.offsetY = offsetY;
            changed = true;
        }
        return changed;
    }

    private float getMinOffsetXLocked() {
        final float viewportWidth = mMagnificationBounds.width();
        return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
    }

    private float getMinOffsetYLocked() {
        final float viewportHeight = mMagnificationBounds.height();
        return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
    }

    /**
     * Sets the currently active user ID.
     *
     * @param userId the currently active user ID
     */
    public void setUserId(int userId) {
        if (mUserId != userId) {
            mUserId = userId;

            synchronized (mLock) {
                if (isMagnifying()) {
                    reset(false);
                }
            }
        }
    }

    /**
     * Resets magnification if magnification and auto-update are both enabled.
     *
     * @param animate whether the animate the transition
     * @return {@code true} if magnification was reset to the disabled state,
     *         {@code false} if magnification is still active
     */
    boolean resetIfNeeded(boolean animate) {
        synchronized (mLock) {
            if (isMagnifying()) {
                reset(animate);
                return true;
            }
            return false;
        }
    }

    void setForceShowMagnifiableBounds(boolean show) {
        if (mRegistered) {
            mWindowManager.setForceShowMagnifiableBounds(show);
        }
    }

    private void getMagnifiedFrameInContentCoordsLocked(Rect outFrame) {
        final float scale = getSentScale();
        final float offsetX = getSentOffsetX();
        final float offsetY = getSentOffsetY();
        getMagnificationBounds(outFrame);
        outFrame.offset((int) -offsetX, (int) -offsetY);
        outFrame.scale(1.0f / scale);
    }

    private void requestRectangleOnScreen(int left, int top, int right, int bottom) {
        synchronized (mLock) {
            final Rect magnifiedFrame = mTempRect;
            getMagnificationBounds(magnifiedFrame);
            if (!magnifiedFrame.intersects(left, top, right, bottom)) {
                return;
            }

            final Rect magnifFrameInScreenCoords = mTempRect1;
            getMagnifiedFrameInContentCoordsLocked(magnifFrameInScreenCoords);

            final float scrollX;
            final float scrollY;
            if (right - left > magnifFrameInScreenCoords.width()) {
                final int direction = TextUtils
                        .getLayoutDirectionFromLocale(Locale.getDefault());
                if (direction == View.LAYOUT_DIRECTION_LTR) {
                    scrollX = left - magnifFrameInScreenCoords.left;
                } else {
                    scrollX = right - magnifFrameInScreenCoords.right;
                }
            } else if (left < magnifFrameInScreenCoords.left) {
                scrollX = left - magnifFrameInScreenCoords.left;
            } else if (right > magnifFrameInScreenCoords.right) {
                scrollX = right - magnifFrameInScreenCoords.right;
            } else {
                scrollX = 0;
            }

            if (bottom - top > magnifFrameInScreenCoords.height()) {
                scrollY = top - magnifFrameInScreenCoords.top;
            } else if (top < magnifFrameInScreenCoords.top) {
                scrollY = top - magnifFrameInScreenCoords.top;
            } else if (bottom > magnifFrameInScreenCoords.bottom) {
                scrollY = bottom - magnifFrameInScreenCoords.bottom;
            } else {
                scrollY = 0;
            }

            final float scale = getScale();
            offsetMagnifiedRegion(scrollX * scale, scrollY * scale, INVALID_ID);
        }
    }

    private void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
        if (Thread.currentThread().getId() == mMainThreadId) {
            mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
        } else {
            mHandler.obtainMessage(MSG_SEND_SPEC_TO_ANIMATION,
                    animate ? 1 : 0, 0, spec).sendToTarget();
        }
    }

    private void onScreenTurnedOff() {
        mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
    }

    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_SEND_SPEC_TO_ANIMATION:
                final boolean animate = msg.arg1 == 1;
                final MagnificationSpec spec = (MagnificationSpec) msg.obj;
                mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
                break;
            case MSG_SCREEN_TURNED_OFF:
                resetIfNeeded(false);
                break;
            case MSG_ON_MAGNIFIED_BOUNDS_CHANGED: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final Region magnifiedBounds = (Region) args.arg1;
                onMagnificationRegionChanged(magnifiedBounds);
                magnifiedBounds.recycle();
                args.recycle();
            } break;
            case MSG_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
                final SomeArgs args = (SomeArgs) msg.obj;
                final int left = args.argi1;
                final int top = args.argi2;
                final int right = args.argi3;
                final int bottom = args.argi4;
                requestRectangleOnScreen(left, top, right, bottom);
                args.recycle();
            } break;
            case MSG_ON_USER_CONTEXT_CHANGED:
                resetIfNeeded(true);
                break;
        }
        return true;
    }

    /**
     * Class responsible for animating spec on the main thread and sending spec
     * updates to the window manager.
     */
    private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener {
        private final WindowManagerInternal mWindowManager;

        /**
         * The magnification spec that was sent to the window manager. This should
         * only be accessed with the lock held.
         */
        private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();

        private final MagnificationSpec mStartMagnificationSpec = MagnificationSpec.obtain();

        private final MagnificationSpec mEndMagnificationSpec = MagnificationSpec.obtain();

        private final MagnificationSpec mTmpMagnificationSpec = MagnificationSpec.obtain();

        /**
         * The animator should only be accessed and modified on the main (e.g. animation) thread.
         */
        private final ValueAnimator mValueAnimator;

        private final Object mLock;

        @GuardedBy("mLock")
        private boolean mEnabled = false;

        private SpecAnimationBridge(Context context, Object lock, WindowManagerInternal wm,
                ValueAnimator animator) {
            mLock = lock;
            mWindowManager = wm;
            final long animationDuration = context.getResources().getInteger(
                    R.integer.config_longAnimTime);
            mValueAnimator = animator;
            mValueAnimator.setDuration(animationDuration);
            mValueAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
            mValueAnimator.setFloatValues(0.0f, 1.0f);
            mValueAnimator.addUpdateListener(this);
        }

        /**
         * 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);
                    }
                }
            }
        }

        public void updateSentSpecMainThread(MagnificationSpec spec, boolean animate) {
            if (mValueAnimator.isRunning()) {
                mValueAnimator.cancel();
            }

            // If the current and sent specs don't match, update the sent spec.
            synchronized (mLock) {
                final boolean changed = !mSentMagnificationSpec.equals(spec);
                if (changed) {
                    if (animate) {
                        animateMagnificationSpecLocked(spec);
                    } else {
                        setMagnificationSpecLocked(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);
            }
        }

        private void animateMagnificationSpecLocked(MagnificationSpec toSpec) {
            mEndMagnificationSpec.setTo(toSpec);
            mStartMagnificationSpec.setTo(mSentMagnificationSpec);
            mValueAnimator.start();
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            synchronized (mLock) {
                if (mEnabled) {
                    float fract = animation.getAnimatedFraction();
                    mTmpMagnificationSpec.scale = mStartMagnificationSpec.scale +
                            (mEndMagnificationSpec.scale - mStartMagnificationSpec.scale) * fract;
                    mTmpMagnificationSpec.offsetX = mStartMagnificationSpec.offsetX +
                            (mEndMagnificationSpec.offsetX - mStartMagnificationSpec.offsetX)
                                    * fract;
                    mTmpMagnificationSpec.offsetY = mStartMagnificationSpec.offsetY +
                            (mEndMagnificationSpec.offsetY - mStartMagnificationSpec.offsetY)
                                    * fract;
                    synchronized (mLock) {
                        setMagnificationSpecLocked(mTmpMagnificationSpec);
                    }
                }
            }
        }
    }

    private static class ScreenStateObserver extends BroadcastReceiver {
        private final Context mContext;
        private final MagnificationController mController;

        public ScreenStateObserver(Context context, MagnificationController controller) {
            mContext = context;
            mController = controller;
        }

        public void register() {
            mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
        }

        public void unregister() {
            mContext.unregisterReceiver(this);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            mController.onScreenTurnedOff();
        }
    }

    // Extra class to get settings so tests can mock it
    public static class SettingsBridge {
        private final ContentResolver mContentResolver;

        public SettingsBridge(ContentResolver contentResolver) {
            mContentResolver = contentResolver;
        }

        public void putMagnificationScale(float value, int userId) {
            Settings.Secure.putFloatForUser(mContentResolver,
                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, value, userId);
        }

        public float getMagnificationScale(int userId) {
            return Settings.Secure.getFloatForUser(mContentResolver,
                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
                    DEFAULT_MAGNIFICATION_SCALE, userId);
        }
    }
}
