/*
 * Copyright (C) 2016 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.accessibilityservice.cts;

import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_WINDOW;
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
import static android.content.pm.PackageManager.FEATURE_WINDOW_MAGNIFICATION;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;

import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibility.cts.common.InstrumentedAccessibilityService;
import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
import android.accessibility.cts.common.ShellCommandBuilder;
import android.accessibilityservice.AccessibilityService.MagnificationController;
import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.MagnificationConfig;
import android.accessibilityservice.cts.activities.AccessibilityWindowQueryActivity;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.platform.test.annotations.AppModeFull;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.widget.Button;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.TestUtils;

import org.junit.AfterClass;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;

import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Class for testing {@link MagnificationController} and the magnification overlay window.
 */
@AppModeFull
@RunWith(AndroidJUnit4.class)
public class AccessibilityMagnificationTest {

    /** Maximum timeout when waiting for a magnification callback. */
    public static final int LISTENER_TIMEOUT_MILLIS = 500;
    /** Maximum animation timeout when waiting for a magnification callback. */
    public static final int LISTENER_ANIMATION_TIMEOUT_MILLIS = 1000;
    public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED =
            "accessibility_display_magnification_enabled";

    private static UiAutomation sUiAutomation;

    private StubMagnificationAccessibilityService mService;
    private Instrumentation mInstrumentation;

    private AccessibilityDumpOnFailureRule mDumpOnFailureRule =
            new AccessibilityDumpOnFailureRule();

    private final ActivityTestRule<AccessibilityWindowQueryActivity> mActivityRule =
            new ActivityTestRule<>(AccessibilityWindowQueryActivity.class, false, false);

    private InstrumentedAccessibilityServiceTestRule<InstrumentedAccessibilityService>
            mInstrumentedAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
                    InstrumentedAccessibilityService.class, false);

    private InstrumentedAccessibilityServiceTestRule<StubMagnificationAccessibilityService>
            mMagnificationAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
                    StubMagnificationAccessibilityService.class, false);

    @Rule
    public final RuleChain mRuleChain = RuleChain
            .outerRule(mActivityRule)
            .around(mMagnificationAccessibilityServiceRule)
            .around(mInstrumentedAccessibilityServiceRule)
            .around(mDumpOnFailureRule);

    @BeforeClass
    public static void oneTimeSetUp() {
        sUiAutomation = InstrumentationRegistry.getInstrumentation()
                .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
        final AccessibilityServiceInfo info = sUiAutomation.getServiceInfo();
        info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
        sUiAutomation.setServiceInfo(info);
    }

    @AfterClass
    public static void postTestTearDown() {
        sUiAutomation.destroy();
    }

    @Before
    public void setUp() throws Exception {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        ShellCommandBuilder.create(sUiAutomation)
                .deleteSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED)
                .run();
        // Starting the service will force the accessibility subsystem to examine its settings, so
        // it will update magnification in the process to disable it.
        mService = mMagnificationAccessibilityServiceRule.enableService();
    }

    @Test
    public void testSetScale() {
        final MagnificationController controller = mService.getMagnificationController();
        final float scale = 2.0f;
        final AtomicBoolean result = new AtomicBoolean();

        mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));

        assertTrue("Failed to set scale", result.get());
        assertEquals("Failed to apply scale", scale, controller.getScale(), 0f);

        mService.runOnServiceSync(() -> result.set(controller.reset(false)));

        assertTrue("Failed to reset", result.get());
        assertEquals("Failed to apply reset", 1.0f, controller.getScale(), 0f);
    }

    @Test
    public void testSetScaleAndCenter() {
        final MagnificationController controller = mService.getMagnificationController();
        final Region region = controller.getMagnificationRegion();
        final Rect bounds = region.getBounds();
        final float scale = 2.0f;
        final float x = bounds.left + (bounds.width() / 4.0f);
        final float y = bounds.top + (bounds.height() / 4.0f);
        final AtomicBoolean setScale = new AtomicBoolean();
        final AtomicBoolean setCenter = new AtomicBoolean();
        final AtomicBoolean result = new AtomicBoolean();

        mService.runOnServiceSync(() -> {
            setScale.set(controller.setScale(scale, false));
            setCenter.set(controller.setCenter(x, y, false));
        });

        assertTrue("Failed to set scale", setScale.get());
        assertEquals("Failed to apply scale", scale, controller.getScale(), 0f);

        assertTrue("Failed to set center", setCenter.get());
        assertEquals("Failed to apply center X", x, controller.getCenterX(), 5.0f);
        assertEquals("Failed to apply center Y", y, controller.getCenterY(), 5.0f);

        mService.runOnServiceSync(() -> result.set(controller.reset(false)));

        assertTrue("Failed to reset", result.get());
        assertEquals("Failed to apply reset", 1.0f, controller.getScale(), 0f);
    }

    @Test
    public void testSetMagnificationConfig_expectedConfig() throws Exception {
        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();
        final AtomicBoolean setConfig = new AtomicBoolean();

        final int targetMode = isWindowModeSupported(mInstrumentation.getContext())
                ? MAGNIFICATION_MODE_WINDOW : MAGNIFICATION_MODE_FULLSCREEN;
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(targetMode)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();

        mService.runOnServiceSync(() -> {
            setConfig.set(controller.setMagnificationConfig(config, false));
        });
        waitUntilMagnificationConfig(controller, config);

        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(config, controller.getMagnificationConfig());

        final float newScale = scale + 1;
        final Region region = controller.getMagnificationRegion();
        final Rect bounds = region.getBounds();
        final float newX = bounds.left + (bounds.width() / 4.0f);
        final float newY = bounds.top + (bounds.height() / 4.0f);
        final MagnificationConfig newConfig = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_FULLSCREEN).setScale(newScale).setCenterX(
                        newX).setCenterY(
                        newY).build();
        mService.runOnServiceSync(() -> {
            controller.setMagnificationConfig(newConfig, false);
        });
        waitUntilMagnificationConfig(controller, newConfig);

        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(newConfig, controller.getMagnificationConfig());
    }

    @Test
    public void testSetConfigWithDefaultModeAndCenter_expectedConfig() throws Exception {
        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 3.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();
        final AtomicBoolean setConfig = new AtomicBoolean();

        final int targetMode = isWindowModeSupported(mInstrumentation.getContext())
                ? MAGNIFICATION_MODE_WINDOW : MAGNIFICATION_MODE_FULLSCREEN;
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(targetMode)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y)
                .build();

        mService.runOnServiceSync(
                () -> setConfig.set(controller.setMagnificationConfig(config, false)));
        waitUntilMagnificationConfig(controller, config);

        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(config, controller.getMagnificationConfig());

        final float newScale = scale + 1;
        final MagnificationConfig newConfig = new MagnificationConfig.Builder()
                .setScale(newScale).build();
        final MagnificationConfig expectedConfig = obtainConfigBuilder(config).setScale(
                newScale).build();

        mService.runOnServiceSync(
                () -> setConfig.set(controller.setMagnificationConfig(newConfig, false)));
        waitUntilMagnificationConfig(controller, expectedConfig);

        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(expectedConfig, controller.getMagnificationConfig());
    }

    @Test
    public void testSetFullScreenConfigWithDefaultValues_windowModeEnabled_expectedConfig()
            throws Exception {
        final boolean windowModeSupported = isWindowModeSupported(mInstrumentation.getContext());
        Assume.assumeTrue("window mode is not available", windowModeSupported);

        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 3.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();
        final AtomicBoolean setConfig = new AtomicBoolean();

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();

        mService.runOnServiceSync(
                () -> setConfig.set(controller.setMagnificationConfig(config, false)));
        waitUntilMagnificationConfig(controller, config);

        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(config, controller.getMagnificationConfig());

        final MagnificationConfig newConfig = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                .build();

        mService.runOnServiceSync(
                () -> setConfig.set(controller.setMagnificationConfig(newConfig, false)));
        final MagnificationConfig expectedConfig = obtainConfigBuilder(config).setMode(
                MAGNIFICATION_MODE_FULLSCREEN).build();

        waitUntilMagnificationConfig(controller, expectedConfig);
        assertTrue("Failed to set config", setConfig.get());
        assertConfigEquals(expectedConfig, controller.getMagnificationConfig());
    }

    @Test
    public void testSetMagnificationConfig_legacyApiExpectedResult() {
        final MagnificationController controller = mService.getMagnificationController();
        final Region region = controller.getMagnificationRegion();
        final Rect bounds = region.getBounds();
        final float scale = 2.0f;
        final float x = bounds.left + (bounds.width() / 4.0f);
        final float y = bounds.top + (bounds.height() / 4.0f);
        final AtomicBoolean setConfig = new AtomicBoolean();
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();
        try {
            mService.runOnServiceSync(() -> {
                setConfig.set(controller.setMagnificationConfig(config, false));
            });

            assertEquals("Failed to apply scale", scale, controller.getScale(), 0f);
            assertEquals("Failed to apply center X", x, controller.getCenterX(), 5.0f);
            assertEquals("Failed to apply center Y", y, controller.getCenterY(), 5.0f);
        } finally {
            mService.runOnServiceSync(() -> controller.resetCurrentMagnification(false));
        }
    }

    @Test
    public void testSetWindowModeConfig_connectionReset_expectedResult() throws Exception {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();

        mService.runOnServiceSync(
                () -> controller.setMagnificationConfig(config, /* animate= */ false));

        waitUntilMagnificationConfig(controller, config);

        // Test service is disabled and enabled to make the connection reset.
        mService.runOnServiceSync(() -> mService.disableSelfAndRemove());
        mService = null;
        InstrumentedAccessibilityService service =
                mMagnificationAccessibilityServiceRule.enableService();
        MagnificationController controller2 = service.getMagnificationController();
        try {
            final float newScale = scale + 1;
            final float newX = x + 10;
            final float newY = y + 10;
            final MagnificationConfig newConfig = new MagnificationConfig.Builder()
                    .setMode(MAGNIFICATION_MODE_WINDOW)
                    .setScale(newScale)
                    .setCenterX(newX)
                    .setCenterY(newY).build();

            service.runOnServiceSync(
                    () -> controller2.setMagnificationConfig(newConfig, /* animate= */ false));

            waitUntilMagnificationConfig(controller2, newConfig);
        } finally {
            service.runOnServiceSync(
                    () -> controller2.resetCurrentMagnification(false));
        }
    }

    @Test
    public void testSetWindowModeConfig_hasMagnificationOverlay() throws TimeoutException {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(2.0f)
                .build();

        try {
            sUiAutomation.executeAndWaitForEvent(
                    () -> controller.setMagnificationConfig(config, false),
                    event -> sUiAutomation.getWindows().stream().anyMatch(
                            accessibilityWindowInfo -> accessibilityWindowInfo.getType()
                                    == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);
        } finally {
            controller.resetCurrentMagnification(false);
        }
    }

    @Test
    public void testServiceConnectionDisconnected_hasNoMagnificationOverlay()
            throws TimeoutException {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(2.0f)
                .build();

        try {
            sUiAutomation.executeAndWaitForEvent(
                    () -> controller.setMagnificationConfig(config, false),
                    event -> sUiAutomation.getWindows().stream().anyMatch(
                            accessibilityWindowInfo -> accessibilityWindowInfo.getType()
                                    == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);

            sUiAutomation.executeAndWaitForEvent(
                    () -> mService.runOnServiceSync(() -> mService.disableSelfAndRemove()),
                    event -> sUiAutomation.getWindows().stream().noneMatch(
                            accessibilityWindowInfo -> accessibilityWindowInfo.getType()
                                    == AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY), 5000);
        } finally {
            controller.resetCurrentMagnification(false);
        }
    }

    @Test
    public void testGetMagnificationConfig_setConfigByLegacyApi_expectedResult() {
        final MagnificationController controller = mService.getMagnificationController();
        final Region region = controller.getMagnificationRegion();
        final Rect bounds = region.getBounds();
        final float scale = 2.0f;
        final float x = bounds.left + (bounds.width() / 4.0f);
        final float y = bounds.top + (bounds.height() / 4.0f);
        mService.runOnServiceSync(() -> {
            controller.setScale(scale, false);
            controller.setCenter(x, y, false);
        });

        final MagnificationConfig config = controller.getMagnificationConfig();

        assertEquals("Failed to apply scale", scale, config.getScale(), 0f);
        assertEquals("Failed to apply center X", x, config.getCenterX(), 5.0f);
        assertEquals("Failed to apply center Y", y, config.getCenterY(), 5.0f);
    }

    @Test
    public void testListener() {
        final MagnificationController controller = mService.getMagnificationController();
        final OnMagnificationChangedListener spyListener = mock(
                OnMagnificationChangedListener.class);
        final OnMagnificationChangedListener listener =
                (controller1, region, scale, centerX, centerY) ->
                        spyListener.onMagnificationChanged(controller1, region, scale, centerX,
                                centerY);
        controller.addListener(listener);

        try {
            final float scale = 2.0f;
            final AtomicBoolean result = new AtomicBoolean();

            mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));

            assertTrue("Failed to set scale", result.get());
            verify(spyListener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), eq(scale), anyFloat(), anyFloat());

            mService.runOnServiceSync(() -> result.set(controller.reset(false)));

            assertTrue("Failed to reset", result.get());
            verify(spyListener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), eq(1.0f), anyFloat(), anyFloat());
        } finally {
            controller.removeListener(listener);
        }
    }

    @Test
    public void testListener_changeConfigByLegacyApi_notifyConfigChanged() {
        final MagnificationController controller = mService.getMagnificationController();
        final OnMagnificationChangedListener listener = mock(OnMagnificationChangedListener.class);
        controller.addListener(listener);

        try {
            final float scale = 2.0f;
            final AtomicBoolean result = new AtomicBoolean();

            mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));

            assertTrue("Failed to set scale", result.get());
            final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                    MagnificationConfig.class);
            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), configCaptor.capture());
            assertEquals(scale, configCaptor.getValue().getScale(), 0);

            reset(listener);
            mService.runOnServiceSync(() -> result.set(controller.reset(false)));

            assertTrue("Failed to reset", result.get());
            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), configCaptor.capture());
            assertEquals(1.0f, configCaptor.getValue().getScale(), 0);
        } finally {
            controller.removeListener(listener);
        }
    }

    @Test
    public void testListener_magnificationConfigChangedWithoutAnimation_notifyConfigChanged()
            throws Exception {
        final MagnificationController controller = mService.getMagnificationController();
        final OnMagnificationChangedListener listener = mock(OnMagnificationChangedListener.class);
        controller.addListener(listener);
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final int targetMode = isWindowModeSupported(mInstrumentation.getContext())
                ? MAGNIFICATION_MODE_WINDOW : MAGNIFICATION_MODE_FULLSCREEN;
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(targetMode)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y)
                .build();

        try {
            mService.runOnServiceSync(() -> controller.setMagnificationConfig(config, false));
            waitUntilMagnificationConfig(controller, config);

            final ArgumentCaptor<MagnificationConfig> configCaptor = ArgumentCaptor.forClass(
                    MagnificationConfig.class);
            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS).atLeastOnce()).onMagnificationChanged(
                    eq(controller), any(Region.class), configCaptor.capture());
            assertConfigEquals(config, configCaptor.getValue());

            final float newScale = scale + 1;
            final float newX = x + 10;
            final float newY = y + 10;
            final MagnificationConfig fullscreenConfig = new MagnificationConfig.Builder()
                    .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                    .setScale(newScale)
                    .setCenterX(newX)
                    .setCenterY(newY).build();

            reset(listener);
            mService.runOnServiceSync(() -> {
                controller.setMagnificationConfig(fullscreenConfig, false);
            });
            waitUntilMagnificationConfig(controller, fullscreenConfig);

            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), configCaptor.capture());
            assertConfigEquals(fullscreenConfig, configCaptor.getValue());
        } finally {
            mService.runOnServiceSync(() -> {
                controller.resetCurrentMagnification(false);
                controller.removeListener(listener);
            });
        }
    }

    @Test
    public void testListener_magnificationConfigChangedWithAnimation_notifyConfigChanged() {
        final MagnificationController controller = mService.getMagnificationController();
        final OnMagnificationChangedListener listener = mock(OnMagnificationChangedListener.class);
        controller.addListener(listener);
        final int targetMode = isWindowModeSupported(mInstrumentation.getContext())
                ? MAGNIFICATION_MODE_WINDOW : MAGNIFICATION_MODE_FULLSCREEN;
        final float scale = 2.0f;
        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(targetMode)
                .setScale(scale).build();

        try {
            mService.runOnServiceSync(
                    () -> controller.setMagnificationConfig(config, /* animate= */ true));

            verify(listener, timeout(LISTENER_ANIMATION_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), any(MagnificationConfig.class));

            final float newScale = scale + 1;
            final MagnificationConfig fullscreenConfig = new MagnificationConfig.Builder()
                    .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                    .setScale(newScale).build();

            reset(listener);
            mService.runOnServiceSync(() -> {
                controller.setMagnificationConfig(fullscreenConfig, /* animate= */ true);
            });

            verify(listener, timeout(LISTENER_ANIMATION_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), any(MagnificationConfig.class));
        } finally {
            mService.runOnServiceSync(() -> {
                controller.resetCurrentMagnification(false);
                controller.removeListener(listener);
            });
        }
    }

    @Test
    public void testMagnificationServiceShutsDownWhileMagnifying_fullscreen_shouldReturnTo1x() {
        final MagnificationController controller = mService.getMagnificationController();
        mService.runOnServiceSync(() -> controller.setScale(2.0f, false));

        mService.runOnServiceSync(() -> mService.disableSelf());
        mService = null;
        InstrumentedAccessibilityService service =
                mInstrumentedAccessibilityServiceRule.enableService();
        final MagnificationController controller2 = service.getMagnificationController();
        assertEquals("Magnification must reset when a service dies",
                1.0f, controller2.getScale(), 0f);
    }

    @Test
    public void testMagnificationServiceShutsDownWhileMagnifying_windowMode_shouldReturnTo1x()
            throws Exception {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();

        mService.runOnServiceSync(() -> {
            controller.setMagnificationConfig(config, false);
        });
        waitUntilMagnificationConfig(controller, config);

        mService.runOnServiceSync(() -> mService.disableSelf());
        mService = null;
        InstrumentedAccessibilityService service =
                mInstrumentedAccessibilityServiceRule.enableService();
        final MagnificationController controller2 = service.getMagnificationController();
        assertEquals("Magnification must reset when a service dies",
                1.0f, controller2.getMagnificationConfig().getScale(), 0f);
    }

    @Test
    public void testGetMagnificationRegion_whenCanControlMagnification_shouldNotBeEmpty() {
        final MagnificationController controller = mService.getMagnificationController();
        Region magnificationRegion = controller.getMagnificationRegion();
        assertFalse("Magnification region should not be empty when "
                 + "magnification is being actively controlled", magnificationRegion.isEmpty());
    }

    @Test
    public void testGetMagnificationRegion_whenCantControlMagnification_shouldBeEmpty() {
        mService.runOnServiceSync(() -> mService.disableSelf());
        mService = null;
        InstrumentedAccessibilityService service =
                mInstrumentedAccessibilityServiceRule.enableService();
        final MagnificationController controller = service.getMagnificationController();
        Region magnificationRegion = controller.getMagnificationRegion();
        assertTrue("Magnification region should be empty when magnification "
                + "is not being actively controlled", magnificationRegion.isEmpty());
    }

    @Test
    public void testGetMagnificationRegion_whenMagnificationGesturesEnabled_shouldNotBeEmpty() {
        ShellCommandBuilder.create(sUiAutomation)
                .putSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, "1")
                .run();
        mService.runOnServiceSync(() -> mService.disableSelf());
        mService = null;
        InstrumentedAccessibilityService service =
                mInstrumentedAccessibilityServiceRule.enableService();
        try {
            final MagnificationController controller = service.getMagnificationController();
            Region magnificationRegion = controller.getMagnificationRegion();
            assertFalse("Magnification region should not be empty when magnification "
                    + "gestures are active", magnificationRegion.isEmpty());
        } finally {
            ShellCommandBuilder.create(sUiAutomation)
                    .deleteSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED)
                    .run();
        }
    }

    @Test
    public void testGetCurrentMagnificationRegion_fullscreen_exactRegionCenter() throws Exception {
        final MagnificationController controller = mService.getMagnificationController();
        final Region region = controller.getMagnificationRegion();
        final Rect bounds = region.getBounds();
        final float scale = 2.0f;
        final float x = bounds.left + (bounds.width() / 4.0f);
        final float y = bounds.top + (bounds.height() / 4.0f);

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_FULLSCREEN)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();
        try {
            mService.runOnServiceSync(() -> {
                controller.setMagnificationConfig(config, false);
            });
            waitUntilMagnificationConfig(controller, config);

            final Region magnificationRegion = controller.getCurrentMagnificationRegion();
            assertFalse(magnificationRegion.isEmpty());
        } finally {
            mService.runOnServiceSync(() -> {
                controller.resetCurrentMagnification(false);
            });
        }
    }

    @Test
    public void testGetCurrentMagnificationRegion_windowMode_exactRegionCenter() throws Exception {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();
        try {
            mService.runOnServiceSync(() -> {
                controller.setMagnificationConfig(config, false);
            });
            waitUntilMagnificationConfig(controller, config);

            final Region magnificationRegion = controller.getCurrentMagnificationRegion();
            final Rect magnificationBounds = magnificationRegion.getBounds();
            assertEquals(magnificationBounds.exactCenterX(), x, 0);
            assertEquals(magnificationBounds.exactCenterY(), y, 0);
        } finally {
            mService.runOnServiceSync(() -> {
                controller.resetCurrentMagnification(false);
            });
        }
    }

    @Test
    public void testResetCurrentMagnificationRegion_WindowMode_regionIsEmpty() throws Exception {
        Assume.assumeTrue(isWindowModeSupported(mInstrumentation.getContext()));

        final MagnificationController controller = mService.getMagnificationController();
        final WindowManager windowManager = mInstrumentation.getContext().getSystemService(
                WindowManager.class);
        final float scale = 2.0f;
        final float x = windowManager.getCurrentWindowMetrics().getBounds().centerX();
        final float y = windowManager.getCurrentWindowMetrics().getBounds().centerY();

        final MagnificationConfig config = new MagnificationConfig.Builder()
                .setMode(MAGNIFICATION_MODE_WINDOW)
                .setScale(scale)
                .setCenterX(x)
                .setCenterY(y).build();

        mService.runOnServiceSync(() -> {
            controller.setMagnificationConfig(config, false);
        });
        waitUntilMagnificationConfig(controller, config);

        assertEquals(scale, controller.getMagnificationConfig().getScale(), 0);

        mService.runOnServiceSync(() -> {
            controller.resetCurrentMagnification(false);
        });

        assertEquals(1.0f, controller.getMagnificationConfig().getScale(), 0);
        assertTrue(controller.getCurrentMagnificationRegion().isEmpty());
    }

    @Test
    public void testAnimatingMagnification() throws InterruptedException {
        final MagnificationController controller = mService.getMagnificationController();
        final int timeBetweenAnimationChanges = 100;

        final float scale1 = 5.0f;
        final float x1 = 500;
        final float y1 = 1000;

        final float scale2 = 4.0f;
        final float x2 = 500;
        final float y2 = 1500;

        final float scale3 = 2.1f;
        final float x3 = 700;
        final float y3 = 700;

        for (int i = 0; i < 5; i++) {
            mService.runOnServiceSync(() -> {
                controller.setScale(scale1, true);
                controller.setCenter(x1, y1, true);
            });

            Thread.sleep(timeBetweenAnimationChanges);

            mService.runOnServiceSync(() -> {
                controller.setScale(scale2, true);
                controller.setCenter(x2, y2, true);
            });

            Thread.sleep(timeBetweenAnimationChanges);

            mService.runOnServiceSync(() -> {
                controller.setScale(scale3, true);
                controller.setCenter(x3, y3, true);
            });

            Thread.sleep(timeBetweenAnimationChanges);
        }
    }

    @Test
    public void testA11yNodeInfoVisibility_whenOutOfMagnifiedArea_shouldVisible()
            throws Exception{
        final Activity activity = launchActivityAndWaitForItToBeOnscreen(
                mInstrumentation, sUiAutomation, mActivityRule);
        final MagnificationController controller = mService.getMagnificationController();
        final Rect magnifyBounds = controller.getMagnificationRegion().getBounds();
        final float scale = 8.0f;
        final Button button = activity.findViewById(R.id.button1);
        adjustViewBoundsIfNeeded(button, scale, magnifyBounds);

        final AccessibilityNodeInfo buttonNode = sUiAutomation.getRootInActiveWindow()
                .findAccessibilityNodeInfosByViewId(
                        "android.accessibilityservice.cts:id/button1").get(0);
        assertNotNull("Can't find button on the screen", buttonNode);
        assertTrue("Button should be visible", buttonNode.isVisibleToUser());

        // Get right-bottom center position
        final float centerX = magnifyBounds.left + (((float) magnifyBounds.width() / (2.0f * scale))
                * ((2.0f * scale) - 1.0f));
        final float centerY = magnifyBounds.top + (((float) magnifyBounds.height() / (2.0f * scale))
                * ((2.0f * scale) - 1.0f));
        try {
            waitOnMagnificationChanged(controller, scale, centerX, centerY);
            // Waiting for UI refresh
            mInstrumentation.waitForIdleSync();
            buttonNode.refresh();

            final Rect boundsInScreen = new Rect();
            final DisplayMetrics displayMetrics = new DisplayMetrics();
            buttonNode.getBoundsInScreen(boundsInScreen);
            activity.getDisplay().getMetrics(displayMetrics);
            final Rect displayRect = new Rect(0, 0,
                    displayMetrics.widthPixels, displayMetrics.heightPixels);
            // The boundsInScreen of button is adjusted to outside of screen by framework,
            // for example, Rect(-xxx, -xxx, -xxx, -xxx). Intersection of button and screen
            // should be empty.
            assertFalse("Button shouldn't be on the screen, screen is " + displayRect
                            + ", button bounds is " + boundsInScreen,
                    Rect.intersects(displayRect, boundsInScreen));
            assertTrue("Button should be visible", buttonNode.isVisibleToUser());
        } finally {
            mService.runOnServiceSync(() -> controller.reset(false));
        }
    }

    private void waitOnMagnificationChanged(MagnificationController controller, float newScale,
            float newCenterX, float newCenterY) {
        final OnMagnificationChangedListener spyListener = mock(
                OnMagnificationChangedListener.class);
        final OnMagnificationChangedListener listener =
                (controller1, region, scale, centerX, centerY) ->
                        spyListener.onMagnificationChanged(controller1, region, scale, centerX,
                                centerY);
        controller.addListener(listener);
        try {
            final AtomicBoolean setScale = new AtomicBoolean();
            final AtomicBoolean setCenter = new AtomicBoolean();
            mService.runOnServiceSync(() -> {
                setScale.set(controller.setScale(newScale, false));
            });

            assertTrue("Failed to set scale", setScale.get());
            verify(spyListener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), eq(newScale), anyFloat(), anyFloat());

            reset(spyListener);
            mService.runOnServiceSync(() -> {
                setCenter.set(controller.setCenter(newCenterX, newCenterY, false));
            });

            assertTrue("Failed to set center", setCenter.get());
            verify(spyListener, timeout(LISTENER_TIMEOUT_MILLIS)).onMagnificationChanged(
                    eq(controller), any(Region.class), anyFloat(), eq(newCenterX), eq(newCenterY));
        } finally {
            controller.removeListener(listener);
        }
    }

    /**
     * Adjust top-left view bounds if it's still in the magnified viewport after sets magnification
     * scale and move centers to bottom-right.
     */
    private void adjustViewBoundsIfNeeded(View topLeftview, float scale, Rect magnifyBounds) {
        final Point magnifyViewportTopLeft = new Point();
        magnifyViewportTopLeft.x = (int)((scale - 1.0f) * ((float) magnifyBounds.width() / scale));
        magnifyViewportTopLeft.y = (int)((scale - 1.0f) * ((float) magnifyBounds.height() / scale));
        magnifyViewportTopLeft.offset(magnifyBounds.left, magnifyBounds.top);

        final int[] viewLocation = new int[2];
        topLeftview.getLocationOnScreen(viewLocation);
        final Rect viewBounds = new Rect(viewLocation[0], viewLocation[1],
                viewLocation[0] + topLeftview.getWidth(),
                viewLocation[1] + topLeftview.getHeight());
        if (viewBounds.right < magnifyViewportTopLeft.x
                && viewBounds.bottom < magnifyViewportTopLeft.y) {
            // no need
            return;
        }

        final ViewGroup.LayoutParams layoutParams = topLeftview.getLayoutParams();
        if (viewBounds.right >= magnifyViewportTopLeft.x) {
            layoutParams.width = topLeftview.getWidth() - 1
                    - (viewBounds.right - magnifyViewportTopLeft.x);
            assertTrue("Needs to fix layout", layoutParams.width > 0);
        }
        if (viewBounds.bottom >= magnifyViewportTopLeft.y) {
            layoutParams.height = topLeftview.getHeight() - 1
                    - (viewBounds.bottom - magnifyViewportTopLeft.y);
            assertTrue("Needs to fix layout", layoutParams.height > 0);
        }
        mInstrumentation.runOnMainSync(() -> topLeftview.setLayoutParams(layoutParams));
        // Waiting for UI refresh
        mInstrumentation.waitForIdleSync();
    }

    private void waitUntilMagnificationConfig(MagnificationController controller,
            MagnificationConfig config) throws Exception {
        TestUtils.waitUntil(
                "Failed to apply the config. expected: " + config + " , actual: "
                        + controller.getMagnificationConfig(), 5,
                () -> {
                    final MagnificationConfig actualConfig = controller.getMagnificationConfig();
                    return actualConfig.getMode() == config.getMode()
                            && Float.compare(actualConfig.getScale(), config.getScale()) == 0
                            && Float.compare(actualConfig.getCenterX(), config.getCenterX()) == 0
                            && Float.compare(actualConfig.getCenterY(), config.getCenterY()) == 0;
                });
    }

    private void assertConfigEquals(MagnificationConfig expected, MagnificationConfig result) {
        assertEquals("Failed to apply mode", expected.getMode(),
                result.getMode(), 0f);
        assertEquals("Failed to apply scale", expected.getScale(),
                result.getScale(), 0f);
        assertEquals("Failed to apply center X", expected.getCenterX(),
                result.getCenterX(), 5.0f);
        assertEquals("Failed to apply center Y", expected.getCenterY(),
                result.getCenterY(), 5.0f);
    }

    private static boolean isWindowModeSupported(Context context) {
        return context.getPackageManager().hasSystemFeature(FEATURE_WINDOW_MAGNIFICATION);
    }

    private static MagnificationConfig.Builder obtainConfigBuilder(MagnificationConfig config) {
        MagnificationConfig.Builder builder = new MagnificationConfig.Builder();
        builder.setMode(config.getMode())
                .setScale(config.getScale())
                .setCenterX(config.getCenterX())
                .setCenterY(config.getCenterY());
        return builder;
    }
}
