/*
 * Copyright (C) 2017 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 android.widget.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Magnifier;
import android.widget.ScrollView;

import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.WidgetTestUtils;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Tests for {@link Magnifier}.
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class MagnifierTest {
    private static final String TIME_LIMIT_EXCEEDED =
            "Completing the magnifier operation took too long";
    private static final float PIXEL_COMPARISON_DELTA = 1f;
    private static final float WINDOW_ELEVATION = 10f;

    private Activity mActivity;
    private LinearLayout mLayout;
    private View mView;
    private Magnifier mMagnifier;
    private DisplayMetrics mDisplayMetrics;

    @Rule
    public ActivityTestRule<MagnifierCtsActivity> mActivityRule =
            new ActivityTestRule<>(MagnifierCtsActivity.class);

    @Before
    public void setup() throws Throwable {
        mActivity = mActivityRule.getActivity();
        PollingCheck.waitFor(mActivity::hasWindowFocus);

        mDisplayMetrics = mActivity.getResources().getDisplayMetrics();
        // Do not run the tests, unless the device screen is big enough to fit a magnifier
        // having the default size.
        assumeTrue(isScreenBigEnough());

        mLayout = mActivity.findViewById(R.id.magnifier_activity_centered_view_layout);
        mView = mActivity.findViewById(R.id.magnifier_centered_view);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mLayout, null);

        mMagnifier = new Magnifier.Builder(mView)
                .setSize(mView.getWidth() / 2, mView.getHeight() / 2)
                .build();
        mActivityRule.runOnUiThread(() -> {
            // Elevate the application window to have non-zero insets inside surface.
            mActivityRule.getActivity().getWindow().setElevation(WINDOW_ELEVATION);
        });
    }

    private boolean isScreenBigEnough() {
        // Get the size of the screen in dp.
        final float dpScreenWidth = mDisplayMetrics.widthPixels / mDisplayMetrics.density;
        final float dpScreenHeight = mDisplayMetrics.heightPixels / mDisplayMetrics.density;
        // Get the size of the magnifier window in dp.
        final PointF dpMagnifier = Magnifier.getMagnifierDefaultSize();

        return dpScreenWidth >= dpMagnifier.x * 1.1 && dpScreenHeight >= dpMagnifier.y * 1.1;
    }

    //***** Tests for constructor *****//

    @Test
    public void testConstructor() {
        new Magnifier(new View(mActivity));
    }

    @Test(expected = NullPointerException.class)
    public void testConstructor_NPE() {
        new Magnifier(null);
    }

    //***** Tests for builder *****//

    @Test
    public void testBuilder_setsPropertiesCorrectly_whenTheyAreValid() {
        final int magnifierWidth = 90;
        final int magnifierHeight = 120;
        final float zoom = 1.5f;
        final int sourceToMagnifierHorizontalOffset = 10;
        final int sourceToMagnifierVerticalOffset = -100;
        final float cornerRadius = 20.0f;
        final float elevation = 15.0f;
        final boolean enableClipping = false;
        final Drawable overlay = new ColorDrawable(Color.BLUE);

        final Magnifier.Builder builder = new Magnifier.Builder(mView)
                .setSize(magnifierWidth, magnifierHeight)
                .setInitialZoom(zoom)
                .setDefaultSourceToMagnifierOffset(sourceToMagnifierHorizontalOffset,
                        sourceToMagnifierVerticalOffset)
                .setCornerRadius(cornerRadius)
                .setInitialZoom(zoom)
                .setElevation(elevation)
                .setOverlay(overlay)
                .setClippingEnabled(enableClipping);
        final Magnifier magnifier = builder.build();

        assertEquals(magnifierWidth, magnifier.getWidth());
        assertEquals(magnifierHeight, magnifier.getHeight());
        assertEquals(zoom, magnifier.getZoom(), 0f);
        assertEquals(Math.round(magnifierWidth / zoom), magnifier.getSourceWidth());
        assertEquals(Math.round(magnifierHeight / zoom), magnifier.getSourceHeight());
        assertEquals(sourceToMagnifierHorizontalOffset,
                magnifier.getDefaultHorizontalSourceToMagnifierOffset());
        assertEquals(sourceToMagnifierVerticalOffset,
                magnifier.getDefaultVerticalSourceToMagnifierOffset());
        assertEquals(cornerRadius, magnifier.getCornerRadius(), 0f);
        assertEquals(elevation, magnifier.getElevation(), 0f);
        assertEquals(enableClipping, magnifier.isClippingEnabled());
        assertEquals(overlay, magnifier.getOverlay());
    }

    @Test(expected = NullPointerException.class)
    public void testBuilder_throwsException_whenViewIsNull() {
        new Magnifier.Builder(null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenWidthIsInvalid() {
        new Magnifier.Builder(mView).setSize(0, 10);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenHeightIsInvalid() {
        new Magnifier.Builder(mView).setSize(10, 0);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenZoomIsZero() {
        new Magnifier.Builder(mView).setInitialZoom(0f);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenZoomIsNegative() {
        new Magnifier.Builder(mView).setInitialZoom(-1f);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenElevationIsInvalid() {
        new Magnifier.Builder(mView).setElevation(-1f);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testBuilder_throwsException_whenCornerRadiusIsNegative() {
        new Magnifier.Builder(mView).setCornerRadius(-1f);
    }

    //***** Tests for default parameters *****//

    private int dpToPixelSize(float dp) {
        return (int) (dp * mDisplayMetrics.density + 0.5f);
    }

    private float dpToPixel(float dp) {
        return dp * mDisplayMetrics.density;
    }

    @Test
    public void testMagnifierDefaultParameters_withDeprecatedConstructor() {
        final Magnifier magnifier = new Magnifier(mView);

        final int width = dpToPixelSize(100f);
        assertEquals(width, magnifier.getWidth());
        final int height = dpToPixelSize(48f);
        assertEquals(height, magnifier.getHeight());
        final float elevation = dpToPixel(4f);
        assertEquals(elevation, magnifier.getElevation(), 0.01f);
        final float zoom = 1.25f;
        assertEquals(zoom, magnifier.getZoom(), 0.01f);
        final int verticalOffset = -dpToPixelSize(42f);
        assertEquals(verticalOffset, magnifier.getDefaultVerticalSourceToMagnifierOffset());
        final int horizontalOffset = dpToPixelSize(0f);
        assertEquals(horizontalOffset, magnifier.getDefaultHorizontalSourceToMagnifierOffset());
        final Context deviceDefaultContext = new ContextThemeWrapper(mView.getContext(),
                android.R.style.Theme_DeviceDefault);
        final TypedArray ta = deviceDefaultContext.obtainStyledAttributes(
                new int[]{android.R.attr.dialogCornerRadius});
        final float dialogCornerRadius = ta.getDimension(0, 0);
        ta.recycle();
        assertEquals(dialogCornerRadius, magnifier.getCornerRadius(), 0.01f);
        final boolean isClippingEnabled = true;
        assertEquals(isClippingEnabled, magnifier.isClippingEnabled());
        final int overlayColor = 0x0EFFFFFF;
        assertEquals(overlayColor, ((ColorDrawable) magnifier.getOverlay()).getColor());
    }

    @Test
    public void testMagnifierDefaultParameters_withBuilder() {
        final Magnifier magnifier = new Magnifier.Builder(mView).build();

        final int width = dpToPixelSize(100f);
        assertEquals(width, magnifier.getWidth());
        final int height = dpToPixelSize(48f);
        assertEquals(height, magnifier.getHeight());
        final float elevation = dpToPixel(4f);
        assertEquals(elevation, magnifier.getElevation(), 0.01f);
        final float zoom = 1.25f;
        assertEquals(zoom, magnifier.getZoom(), 0.01f);
        final int verticalOffset = -dpToPixelSize(42f);
        assertEquals(verticalOffset, magnifier.getDefaultVerticalSourceToMagnifierOffset());
        final int horizontalOffset = dpToPixelSize(0f);
        assertEquals(horizontalOffset, magnifier.getDefaultHorizontalSourceToMagnifierOffset());
        final float dialogCornerRadius = dpToPixel(2f);
        assertEquals(dialogCornerRadius, magnifier.getCornerRadius(), 0.01f);
        final boolean isClippingEnabled = true;
        assertEquals(isClippingEnabled, magnifier.isClippingEnabled());
        final int overlayColor = 0x00FFFFFF;
        assertEquals(overlayColor, ((ColorDrawable) magnifier.getOverlay()).getColor());
    }

    @Test
    @UiThreadTest
    public void testSizeAndZoom_areValid() {
        mMagnifier = new Magnifier(mView);
        // Size should be positive.
        assertTrue(mMagnifier.getWidth() > 0);
        assertTrue(mMagnifier.getHeight() > 0);
        // Source size should be positive.
        assertTrue(mMagnifier.getSourceWidth() > 0);
        assertTrue(mMagnifier.getSourceHeight() > 0);
        // The magnified view region should be zoomed in, not out.
        assertTrue(mMagnifier.getZoom() > 1.0f);
    }


    //***** Tests for #show() *****//

    @Test
    public void testShow() throws Throwable {
        final float xCenter = mView.getWidth() / 2f;
        final float yCenter = mView.getHeight() / 2f;
        showMagnifier(xCenter, yCenter);

        final int[] viewLocationInWindow = new int[2];
        mView.getLocationInWindow(viewLocationInWindow);

        // Check the coordinates of the content being copied.
        final Point sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(xCenter + viewLocationInWindow[0],
                sourcePosition.x + mMagnifier.getSourceWidth() / 2f, PIXEL_COMPARISON_DELTA);
        assertEquals(yCenter + viewLocationInWindow[1],
                sourcePosition.y + mMagnifier.getSourceHeight() / 2f, PIXEL_COMPARISON_DELTA);

        // Check the coordinates of the magnifier.
        final Point magnifierPosition = mMagnifier.getPosition();
        assertNotNull(magnifierPosition);
        assertEquals(sourcePosition.x + mMagnifier.getDefaultHorizontalSourceToMagnifierOffset()
                        - mMagnifier.getWidth() / 2f + mMagnifier.getSourceWidth() / 2f,
                magnifierPosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(sourcePosition.y + mMagnifier.getDefaultVerticalSourceToMagnifierOffset()
                        - mMagnifier.getHeight() / 2f + mMagnifier.getSourceHeight() / 2f,
                magnifierPosition.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testShow_doesNotCrash_whenCalledWithExtremeCoordinates() throws Throwable {
        showMagnifier(Integer.MIN_VALUE, Integer.MIN_VALUE);
        showMagnifier(Integer.MIN_VALUE, Integer.MAX_VALUE);
        showMagnifier(Integer.MAX_VALUE, Integer.MIN_VALUE);
        showMagnifier(Integer.MAX_VALUE, Integer.MAX_VALUE);
    }

    @Test
    public void testShow_withDecoupledMagnifierPosition() throws Throwable {
        final float xCenter = mView.getWidth() / 2;
        final float yCenter = mView.getHeight() / 2;

        final int xMagnifier = -20;
        final int yMagnifier = -10;
        showMagnifier(xCenter, yCenter, xMagnifier, yMagnifier);

        final int[] viewLocationInWindow = new int[2];
        mView.getLocationInWindow(viewLocationInWindow);
        final Point magnifierPosition = mMagnifier.getPosition();
        assertNotNull(magnifierPosition);
        assertEquals(
                viewLocationInWindow[0] + xMagnifier - mMagnifier.getWidth() / 2,
                magnifierPosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(
                viewLocationInWindow[1] + yMagnifier - mMagnifier.getHeight() / 2,
                magnifierPosition.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testShow_whenPixelCopyFails() throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_centered_surfaceview_layout);
        }, false /*forceLayout*/);
        final View view = mActivity.findViewById(R.id.magnifier_centered_view);

        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = new Magnifier.Builder(view).build());
        // The PixelCopy will fail as no draw has been done so far to the SurfaceView.
        showMagnifier(0f, 0f);

        assertNull(mMagnifier.getPosition());
        assertNull(mMagnifier.getSourcePosition());
        assertNull(mMagnifier.getContent());
    }

    //***** Tests for #dismiss() *****//

    @Test
    public void testDismiss_doesNotCrash() throws Throwable {
        showMagnifier(0, 0);
        final CountDownLatch latch = new CountDownLatch(1);
        mActivityRule.runOnUiThread(() -> {
            mMagnifier.dismiss();
            mMagnifier.dismiss();
            mMagnifier.show(0, 0);
            mMagnifier.dismiss();
            mMagnifier.dismiss();
            latch.countDown();
        });
        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(2, TimeUnit.SECONDS));
    }

    //***** Tests for #update() *****//

    @Test
    public void testUpdate_doesNotCrash() throws Throwable {
        showMagnifier(0, 0);
        final CountDownLatch latch = new CountDownLatch(1);
        mActivityRule.runOnUiThread(() -> {
            mMagnifier.update();
            mMagnifier.update();
            mMagnifier.show(10, 10);
            mMagnifier.update();
            mMagnifier.update();
            mMagnifier.dismiss();
            mMagnifier.update();
            latch.countDown();
        });
        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(2, TimeUnit.SECONDS));
    }

    @Test
    public void testMagnifierContent_refreshesAfterUpdate() throws Throwable {
        prepareFourQuadrantsScenario();

        // Show the magnifier at the center of the activity.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2);

        final Bitmap initialBitmap = mMagnifier.getContent()
                .copy(mMagnifier.getContent().getConfig(), true);
        assertFourQuadrants(initialBitmap);

        // Make the one quadrant white.
        final View quadrant1 =
                mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout_quadrant_1);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, quadrant1, () -> {
            quadrant1.setBackground(null);
        });

        // Update the magnifier.
        runAndWaitForMagnifierOperationComplete(mMagnifier::update);

        final Bitmap newBitmap = mMagnifier.getContent();
        assertFourQuadrants(newBitmap);
        assertFalse(newBitmap.sameAs(initialBitmap));
    }

    //***** Tests for the position of the magnifier *****//

    @Test
    public void testWindowPosition_isClampedInsideMainApplicationWindow_topLeft() throws Throwable {
        prepareFourQuadrantsScenario();

        // Magnify the center of the activity in a magnifier outside bounds.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2,
                -mMagnifier.getWidth(), -mMagnifier.getHeight());

        // The window should have been positioned to the top left of the activity,
        // such that it does not overlap system insets.
        final Insets systemInsets = mLayout.getRootWindowInsets().getSystemWindowInsets();
        final Point magnifierCoords = mMagnifier.getPosition();
        assertNotNull(magnifierCoords);
        assertEquals(systemInsets.left, magnifierCoords.x, PIXEL_COMPARISON_DELTA);
        assertEquals(systemInsets.top, magnifierCoords.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testWindowPosition_isClampedInsideMainApplicationWindow_bottomRight()
            throws Throwable {
        prepareFourQuadrantsScenario();

        // Magnify the center of the activity in a magnifier outside bounds.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2,
                mLayout.getRootView().getWidth() + mMagnifier.getWidth(),
                mLayout.getRootView().getHeight() + mMagnifier.getHeight());

        // The window should have been positioned to the bottom right of the activity.
        final Insets systemInsets = mLayout.getRootWindowInsets().getSystemWindowInsets();
        final Point magnifierCoords = mMagnifier.getPosition();
        assertNotNull(magnifierCoords);
        assertEquals(mLayout.getRootView().getWidth()
                        - systemInsets.right - mMagnifier.getWidth(),
                magnifierCoords.x, PIXEL_COMPARISON_DELTA);
        assertEquals(mLayout.getRootView().getHeight()
                        - systemInsets.bottom - mMagnifier.getHeight(),
                magnifierCoords.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testWindowPosition_isNotClamped_whenClampingFlagIsOff_topLeft() throws Throwable {
        prepareFourQuadrantsScenario();
        mMagnifier = new Magnifier.Builder(mLayout)
                .setClippingEnabled(false)
                .build();

        // Magnify the center of the activity in a magnifier outside bounds.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2,
                -mMagnifier.getWidth(), -mMagnifier.getHeight());

        // The window should have not been clamped.
        final Point magnifierCoords = mMagnifier.getPosition();
        final int[] magnifiedViewPosition = new int[2];
        mLayout.getLocationInWindow(magnifiedViewPosition);
        assertNotNull(magnifierCoords);
        assertEquals(magnifiedViewPosition[0] - 3 * mMagnifier.getWidth() / 2, magnifierCoords.x,
                PIXEL_COMPARISON_DELTA);
        assertEquals(magnifiedViewPosition[1] - 3 * mMagnifier.getHeight() / 2, magnifierCoords.y,
                PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testWindowPosition_isNotClamped_whenClampingFlagIsOff_bottomRight()
            throws Throwable {
        prepareFourQuadrantsScenario();
        mMagnifier = new Magnifier.Builder(mLayout)
                .setClippingEnabled(false)
                .setSize(40, 40)
                .build();

        // Magnify the center of the activity in a magnifier outside bounds.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2,
                mLayout.getRootView().getWidth() + mMagnifier.getWidth(),
                mLayout.getRootView().getHeight() + mMagnifier.getHeight());

        // The window should have not been clamped.
        final Point magnifierCoords = mMagnifier.getPosition();
        final int[] magnifiedViewPosition = new int[2];
        mLayout.getLocationInWindow(magnifiedViewPosition);
        assertNotNull(magnifierCoords);
        assertEquals(magnifiedViewPosition[0] + mLayout.getRootView().getWidth()
                        + mMagnifier.getWidth() / 2, magnifierCoords.x, PIXEL_COMPARISON_DELTA);
        assertEquals(magnifiedViewPosition[1] + mLayout.getRootView().getHeight()
                        + mMagnifier.getHeight() / 2, magnifierCoords.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testWindowPosition_isCorrect_whenADefaultContentToMagnifierOffsetIsUsed()
            throws Throwable {
        prepareFourQuadrantsScenario();
        final int horizontalOffset = 5;
        final int verticalOffset = -10;
        mMagnifier = new Magnifier.Builder(mLayout)
                .setSize(20, 10) /* make magnifier small to avoid having it clamped */
                .setDefaultSourceToMagnifierOffset(horizontalOffset, verticalOffset)
                .build();

        // Magnify the center of the activity in a magnifier outside bounds.
        showMagnifier(mLayout.getWidth() / 2, mLayout.getHeight() / 2);

        final Point magnifierCoords = mMagnifier.getPosition();
        final Point sourceCoords = mMagnifier.getSourcePosition();
        assertNotNull(magnifierCoords);
        assertEquals(sourceCoords.x + mMagnifier.getSourceWidth() / 2f + horizontalOffset,
                magnifierCoords.x + mMagnifier.getWidth() / 2f, PIXEL_COMPARISON_DELTA);
        assertEquals(sourceCoords.y + mMagnifier.getSourceHeight() / 2f + verticalOffset,
                magnifierCoords.y + mMagnifier.getHeight() / 2f, PIXEL_COMPARISON_DELTA);
    }

    @Test
    @UiThreadTest
    public void testWindowPosition_isNull_whenMagnifierIsNotShowing() {
        mMagnifier = new Magnifier.Builder(mLayout)
                .setSize(20, 10) /* make magnifier small to avoid having it clamped */
                .build();

        // No #show has been requested, so the position should be null.
        assertNull(mMagnifier.getPosition());
        // #show should make the position not null.
        mMagnifier.show(0, 0);
        assertNotNull(mMagnifier.getPosition());
        // #dismiss should make the position null.
        mMagnifier.dismiss();
        assertNull(mMagnifier.getPosition());
    }

    //***** Tests for the position of the content copied to the magnifier *****//

    @Test
    @UiThreadTest
    public void testSourcePosition_isNull_whenMagnifierIsNotShowing() {
        mMagnifier = new Magnifier.Builder(mLayout)
                .setSize(20, 10) /* make magnifier small to avoid having it clamped */
                .build();

        // No #show has been requested, so the source position should be null.
        assertNull(mMagnifier.getSourcePosition());
        // #show should make the source position not null.
        mMagnifier.show(0, 0);
        assertNotNull(mMagnifier.getSourcePosition());
        // #dismiss should make the source position null.
        mMagnifier.dismiss();
        assertNull(mMagnifier.getSourcePosition());
    }

    @Test
    public void testSourcePosition_respectsMaxVisibleBounds_inHorizontalScrollableContainer()
            throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_scrollable_views_layout);
        }, false /*forceLayout*/);
        final View view = mActivity
                .findViewById(R.id.magnifier_activity_horizontally_scrolled_view);
        final HorizontalScrollView container = (HorizontalScrollView) mActivity
                .findViewById(R.id.horizontal_scroll_container);
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(100, 100)
                .setInitialZoom(20f) /* 5x5 source size */
                .setSourceBounds(
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE
                );

        runOnUiThreadAndWaitForCompletion(() -> {
            mMagnifier = builder.build();
            // Scroll halfway horizontally.
            container.scrollTo(view.getWidth() / 2, 0);
        });

        final int[] containerPosition = new int[2];
        container.getLocationInWindow(containerPosition);

        // Try to copy from an x to the left of the currently visible region.
        showMagnifier(view.getWidth() / 4, 0);
        Point sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(containerPosition[0], sourcePosition.x, PIXEL_COMPARISON_DELTA);

        // Try to copy from an x to the right of the currently visible region.
        showMagnifier(3 * view.getWidth() / 4, 0);
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(containerPosition[0] + container.getWidth() - mMagnifier.getSourceWidth(),
                sourcePosition.x, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testSourcePosition_respectsMaxVisibleBounds_inVerticalScrollableContainer()
            throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_scrollable_views_layout);
        }, false /*forceLayout*/);
        final View view = mActivity.findViewById(R.id.magnifier_activity_vertically_scrolled_view);
        final ScrollView container = (ScrollView) mActivity
                .findViewById(R.id.vertical_scroll_container);
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(100, 100)
                .setInitialZoom(10f) /* 10x10 source size */
                .setSourceBounds(
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE
                );

        runOnUiThreadAndWaitForCompletion(() -> {
            mMagnifier = builder.build();
            // Scroll halfway vertically.
            container.scrollTo(0, view.getHeight() / 2);
        });

        final int[] containerPosition = new int[2];
        container.getLocationInWindow(containerPosition);

        // Try to copy from an y above the currently visible region.
        showMagnifier(0, view.getHeight() / 4);
        Point sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(containerPosition[1], sourcePosition.y, PIXEL_COMPARISON_DELTA);

        // Try to copy from an x below the currently visible region.
        showMagnifier(0, 3 * view.getHeight() / 4);
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(containerPosition[1] + container.getHeight() - mMagnifier.getSourceHeight(),
                sourcePosition.y, PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testSourcePosition_respectsMaxInSurfaceBounds() throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_centered_view_layout);
        }, false /*forceLayout*/);
        final View view = mActivity.findViewById(R.id.magnifier_centered_view);
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(100, 100)
                .setInitialZoom(5f) /* 20x20 source size */
                .setSourceBounds(
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE
                );

        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        final int[] viewPosition = new int[2];
        view.getLocationInWindow(viewPosition);

        // Copy content centered on relative position (0, 0) and expect the top left
        // corner of the source NOT to have been pulled to coincide with (0, 0) of the view.
        showMagnifier(0, 0);
        Point sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(viewPosition[0] - mMagnifier.getSourceWidth() / 2, sourcePosition.x,
                PIXEL_COMPARISON_DELTA);
        assertEquals(viewPosition[1] - mMagnifier.getSourceHeight() / 2, sourcePosition.y,
                PIXEL_COMPARISON_DELTA);

        // Copy content centered on the bottom right corner of the view and expect the top left
        // corner of the source NOT to have been pulled inside the view.
        showMagnifier(view.getWidth(), view.getHeight());
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(viewPosition[0] + view.getWidth() - mMagnifier.getSourceWidth() / 2,
                sourcePosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(viewPosition[1] + view.getHeight() - mMagnifier.getSourceHeight() / 2,
                sourcePosition.y, PIXEL_COMPARISON_DELTA);

        final int[] viewPositionInSurface = new int[2];
        view.getLocationInSurface(viewPositionInSurface);
        // Copy content centered on the top left corner of the main app surface and expect the top
        // left corner of the source to have been pulled to the top left corner of the surface.
        showMagnifier(-viewPositionInSurface[0], -viewPositionInSurface[1]);
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(0, sourcePosition.x - viewPosition[0] + viewPositionInSurface[0],
                PIXEL_COMPARISON_DELTA);
        assertEquals(0, sourcePosition.y - viewPosition[1] + viewPositionInSurface[1],
                PIXEL_COMPARISON_DELTA);

        // Copy content below and to the right of the bottom right corner of the main app surface
        // and expect the source to have been pulled inside the surface at its bottom right.
        showMagnifier(2 * view.getRootView().getWidth(), 2 * view.getRootView().getHeight());
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertTrue(
                sourcePosition.x < 2 * view.getRootView().getWidth() - mMagnifier.getSourceWidth());
        assertTrue(sourcePosition.x > view.getRootView().getWidth() - mMagnifier.getSourceWidth());
        assertTrue(sourcePosition.y
                < 2 * view.getRootView().getHeight() - mMagnifier.getSourceHeight());
        assertTrue(sourcePosition.y
                > view.getRootView().getHeight() - mMagnifier.getSourceHeight());
    }

    @Test
    public void testSourcePosition_respectsMaxInSurfaceBounds_forSurfaceView() throws Throwable {
        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_centered_surfaceview_layout);
        }, false /* forceLayout */);
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            // Draw something in the SurfaceView for the Magnifier to copy.
            final View view = mActivity.findViewById(R.id.magnifier_centered_view);
            final SurfaceHolder surfaceHolder = ((SurfaceView) view).getHolder();
            final Canvas canvas = surfaceHolder.lockHardwareCanvas();
            canvas.drawColor(Color.BLUE);
            surfaceHolder.unlockCanvasAndPost(canvas);
        }, false /* forceLayout */);
        final View view = mActivity.findViewById(R.id.magnifier_centered_view);
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(100, 100)
                .setInitialZoom(5f) /* 20x20 source size */
                .setSourceBounds(
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE,
                        Magnifier.SOURCE_BOUND_MAX_IN_SURFACE
                );

        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        // Copy content centered on relative position (0, 0) and expect the top left
        // corner of the source to have been pulled to coincide with (0, 0) of the view
        // (since the view coincides with the surface content is copied from).
        showMagnifier(0, 0);
        Point sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(0, sourcePosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(0, sourcePosition.y, PIXEL_COMPARISON_DELTA);

        // Copy content centered on the bottom right corner of the view and expect the top left
        // corner of the source to have been pulled inside the surface view.
        showMagnifier(view.getWidth(), view.getHeight());
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(view.getWidth() - mMagnifier.getSourceWidth(), sourcePosition.x);
        assertEquals(view.getHeight() - mMagnifier.getSourceHeight(), sourcePosition.y);

        // Copy content from the center of the surface view and expect no clamping to be done.
        showMagnifier(view.getWidth() / 2, view.getHeight() / 2);
        sourcePosition = mMagnifier.getSourcePosition();
        assertNotNull(sourcePosition);
        assertEquals(view.getWidth() / 2 - mMagnifier.getSourceWidth() / 2, sourcePosition.x,
                PIXEL_COMPARISON_DELTA);
        assertEquals(view.getHeight() / 2 - mMagnifier.getSourceHeight() / 2, sourcePosition.y,
                PIXEL_COMPARISON_DELTA);
    }

    @Test
    public void testSourceBounds_areAdjustedWhenInvalid() throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_centered_view_layout);
        }, false /*forceLayout*/);
        final View view = mActivity.findViewById(R.id.magnifier_centered_view);
        final Insets systemInsets = view.getRootWindowInsets().getSystemWindowInsets();
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(2 * view.getWidth() + systemInsets.right,
                        2 * view.getHeight() + systemInsets.bottom)
                .setInitialZoom(1f) /* source double the size of the view + right/bottom insets */
                .setSourceBounds(/* invalid bounds */
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE,
                        Magnifier.SOURCE_BOUND_MAX_VISIBLE
                );

        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        final int[] viewPosition = new int[2];
        view.getLocationInWindow(viewPosition);

        // Make sure that the left and top bounds are respected, since this is possible
        // for this source size, when the view is centered.
        showMagnifier(0, 0);
        Point sourcePosition = mMagnifier.getSourcePosition();
        assertEquals(viewPosition[0], sourcePosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(viewPosition[1], sourcePosition.y, PIXEL_COMPARISON_DELTA);

        // Move the magnified view to the top left of the screen, and make sure that
        // the top and left bounds are still respected.
        mActivityRule.runOnUiThread(() -> {
            final LinearLayout layout =
                    mActivity.findViewById(R.id.magnifier_activity_centered_view_layout);
            layout.setGravity(Gravity.TOP | Gravity.LEFT);
        });
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, view, null);
        view.getLocationInWindow(viewPosition);

        showMagnifier(0, 0);
        sourcePosition = mMagnifier.getSourcePosition();
        assertEquals(viewPosition[0], sourcePosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(viewPosition[1], sourcePosition.y, PIXEL_COMPARISON_DELTA);

        // Move the magnified view to the bottom right of the layout, and expect the top and left
        // bounds to have been shifted such that the source sits inside the surface.
        mActivityRule.runOnUiThread(() -> {
            final LinearLayout layout =
                    mActivity.findViewById(R.id.magnifier_activity_centered_view_layout);
            layout.setGravity(Gravity.BOTTOM | Gravity.RIGHT);
        });
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, view, null);
        view.getLocationInSurface(viewPosition);

        showMagnifier(0, 0);
        sourcePosition = mMagnifier.getSourcePosition();
        assertEquals(viewPosition[0] - view.getWidth(), sourcePosition.x, PIXEL_COMPARISON_DELTA);
        assertEquals(viewPosition[1] - view.getHeight(), sourcePosition.y, PIXEL_COMPARISON_DELTA);
    }

    //***** Tests for zoom change *****//

    @Test
    public void testZoomChange() throws Throwable {
        // Setup.
        final View view = new View(mActivity);
        final int width = 300;
        final int height = 270;
        final Magnifier.Builder builder = new Magnifier.Builder(view)
                .setSize(width, height)
                .setInitialZoom(1.0f);
        mMagnifier = builder.build();
        final float newZoom = 1.5f;
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, view, () -> {
            mLayout.addView(view, new LayoutParams(200, 200));
            mMagnifier.setZoom(newZoom);
        });
        assertEquals((int) (width / newZoom), mMagnifier.getSourceWidth());
        assertEquals((int) (height / newZoom), mMagnifier.getSourceHeight());

        // Show.
        showMagnifier(200, 200);

        // Check bitmap size.
        assertNotNull(mMagnifier.getOriginalContent());
        assertEquals((int) (width / newZoom), mMagnifier.getOriginalContent().getWidth());
        assertEquals((int) (height / newZoom), mMagnifier.getOriginalContent().getHeight());
    }

    @Test(expected = IllegalArgumentException.class)
    public void testZoomChange_throwsException_whenZoomIsZero() {
        final View view = new View(mActivity);
        new Magnifier(view).setZoom(0f);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testZoomChange_throwsException_whenZoomIsNegative() {
        final View view = new View(mActivity);
        new Magnifier(view).setZoom(-1f);
    }

    //***** Tests for overlay *****//

    @Test
    public void testOverlay_isDrawn() throws Throwable {
        final Magnifier.Builder builder = new Magnifier.Builder(mView)
                .setSize(50, 50)
                .setOverlay(new ColorDrawable(Color.BLUE));
        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        showMagnifier(0, 0);
        // Assert that the content has the correct size and is all blue.
        final Bitmap content = mMagnifier.getContent();
        assertNotNull(content);
        assertEquals(mMagnifier.getWidth(), content.getWidth());
        assertEquals(mMagnifier.getHeight(), content.getHeight());
        for (int i = 0; i < content.getWidth(); ++i) {
            for (int j = 0; j < content.getHeight(); ++j) {
                assertEquals(Color.BLUE, content.getPixel(i, j));
            }
        }
    }

    @Test
    public void testOverlay_redrawsOnInvalidation() throws Throwable {
        final ColorDrawable overlay = new ColorDrawable(Color.BLUE);
        final Magnifier.Builder builder = new Magnifier.Builder(mView)
                .setSize(50, 50)
                .setOverlay(overlay);
        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        showMagnifier(0, 0);
        overlay.setColor(Color.WHITE);
        // Assert that the content has the correct size and is all blue.
        final Bitmap content = mMagnifier.getContent();
        assertNotNull(content);
        assertEquals(mMagnifier.getWidth(), content.getWidth());
        assertEquals(mMagnifier.getHeight(), content.getHeight());
        for (int i = 0; i < content.getWidth(); ++i) {
            for (int j = 0; j < content.getHeight(); ++j) {
                assertEquals(Color.WHITE, content.getPixel(i, j));
            }
        }
    }

    @Test
    public void testOverlay_isNotVisible_whenSetToNull() throws Throwable {
        final Magnifier.Builder builder = new Magnifier.Builder(mView)
                .setSize(50, 50)
                .setInitialZoom(10f) /* 5x5 source size */
                .setOverlay(null);
        runOnUiThreadAndWaitForCompletion(() -> mMagnifier = builder.build());

        showMagnifier(mView.getWidth() / 2, mView.getHeight() / 2);
        // Assert that the content has the correct size and is all the view color.
        final Bitmap content = mMagnifier.getContent();
        assertNotNull(content);
        assertEquals(mMagnifier.getWidth(), content.getWidth());
        assertEquals(mMagnifier.getHeight(), content.getHeight());
        final int viewColor = mView.getContext().getResources().getColor(
                android.R.color.holo_blue_bright, null);
        for (int i = 0; i < content.getWidth(); ++i) {
            for (int j = 0; j < content.getHeight(); ++j) {
                assertEquals(viewColor, content.getPixel(i, j));
            }
        }
    }

    //***** Helper methods / classes *****//

    private void showMagnifier(float sourceX, float sourceY) throws Throwable {
        runAndWaitForMagnifierOperationComplete(() -> mMagnifier.show(sourceX, sourceY));
    }

    private void showMagnifier(float sourceX, float sourceY, float magnifierX, float magnifierY)
            throws Throwable {
        runAndWaitForMagnifierOperationComplete(() -> mMagnifier.show(sourceX, sourceY,
                magnifierX, magnifierY));
    }

    private void runAndWaitForMagnifierOperationComplete(final Runnable lambda) throws Throwable {
        final CountDownLatch latch = new CountDownLatch(1);
        mMagnifier.setOnOperationCompleteCallback(latch::countDown);
        mActivityRule.runOnUiThread(lambda);
        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(2, TimeUnit.SECONDS));
    }

    private void runOnUiThreadAndWaitForCompletion(final Runnable lambda) throws Throwable {
        final CountDownLatch latch = new CountDownLatch(1);
        mActivityRule.runOnUiThread(() -> {
            lambda.run();
            latch.countDown();
        });
        assertTrue(TIME_LIMIT_EXCEEDED, latch.await(2, TimeUnit.SECONDS));
    }

    /**
     * Sets the activity to contain four equal quadrants coloured differently and
     * instantiates a magnifier. This method should not be called on the UI thread.
     */
    private void prepareFourQuadrantsScenario() throws Throwable {
        WidgetTestUtils.runOnMainAndLayoutSync(mActivityRule, () -> {
            mActivity.setContentView(R.layout.magnifier_activity_four_quadrants_layout);
            mLayout = mActivity.findViewById(R.id.magnifier_activity_four_quadrants_layout);
            mMagnifier = new Magnifier(mLayout);
        }, false /*forceLayout*/);
        WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mLayout, null);
    }

    /**
     * Asserts that the current bitmap contains four different dominant colors, which
     * are (almost) equally distributed. The test takes into account an amount of
     * noise, possible consequence of upscaling and filtering the magnified content.
     *
     * @param bitmap the bitmap to be checked
     */
    private void assertFourQuadrants(final Bitmap bitmap) {
        final int expectedQuadrants = 4;
        final int totalPixels = bitmap.getWidth() * bitmap.getHeight();

        final Map<Integer, Integer> colorCount = new HashMap<>();
        for (int x = 0; x < bitmap.getWidth(); ++x) {
            for (int y = 0; y < bitmap.getHeight(); ++y) {
                final int currentColor = bitmap.getPixel(x, y);
                colorCount.put(currentColor, colorCount.getOrDefault(currentColor, 0) + 1);
            }
        }
        assertTrue(colorCount.size() >= expectedQuadrants);

        final List<Integer> counts = new ArrayList<>(colorCount.values());
        Collections.sort(counts);

        int quadrantsTotal = 0;
        for (int i = counts.size() - expectedQuadrants; i < counts.size(); ++i) {
            quadrantsTotal += counts.get(i);
        }
        assertTrue(1.0f * (totalPixels - quadrantsTotal) / totalPixels <= 0.1f);

        for (int i = counts.size() - expectedQuadrants; i < counts.size(); ++i) {
            final float proportion = 1.0f
                    * Math.abs(expectedQuadrants * counts.get(i) - quadrantsTotal) / quadrantsTotal;
            assertTrue(proportion <= 0.1f);
        }
    }
}
