/*
 * 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.server.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.server.wm.CliIntentExtra.extraString;
import static android.server.wm.ComponentNameUtils.getActivityName;
import static android.server.wm.UiDeviceUtils.pressHomeButton;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
import static android.server.wm.app.Components.ANIMATION_TEST_ACTIVITY;
import static android.server.wm.app.Components.ASSISTANT_ACTIVITY;
import static android.server.wm.app.Components.ASSISTANT_VOICE_INTERACTION_SERVICE;
import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_DISPLAY_ID;
import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_ENTER_PIP;
import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_FINISH_SELF;
import static android.server.wm.app.Components.AssistantActivity.EXTRA_ASSISTANT_LAUNCH_NEW_TASK;
import static android.server.wm.app.Components.DOCKED_ACTIVITY;
import static android.server.wm.app.Components.LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION;
import static android.server.wm.app.Components.LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK;
import static android.server.wm.app.Components.LaunchAssistantActivityIntoAssistantStack.EXTRA_ASSISTANT_IS_TRANSLUCENT;
import static android.server.wm.app.Components.PIP_ACTIVITY;
import static android.server.wm.app.Components.PipActivity.EXTRA_ENTER_PIP;
import static android.server.wm.app.Components.TEST_ACTIVITY;
import static android.server.wm.app.Components.TRANSLUCENT_ASSISTANT_ACTIVITY;
import static android.server.wm.app.Components.TestActivity.TEST_ACTIVITY_ACTION_FINISH_SELF;
import static android.view.Display.DEFAULT_DISPLAY;

import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.server.wm.settings.SettingsSession;

import org.junit.Ignore;
import org.junit.Test;

/**
 * Build/Install/Run:
 *     atest CtsWindowManagerDeviceTestCases:AssistantStackTests
 */
@Presubmit
public class AssistantStackTests extends ActivityManagerTestBase {

    private int mAssistantDisplayId = DEFAULT_DISPLAY;
    private int mDefaultWindowingMode;

    public void setUp() throws Exception {
        super.setUp();
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);
            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK);
            waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            WindowManagerState.Task assistantStack =
                    mWmState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT);
            mAssistantDisplayId = assistantStack.mDisplayId;
            mDefaultWindowingMode = getDefaultDisplayWindowingMode();
        }
    }

    @Test
    public void testLaunchingAssistantActivityIntoAssistantStack() throws Exception {
        // Enable the assistant and launch an assistant activity
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
            waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);

            // Ensure that the activity launched in the fullscreen assistant stack
            assertAssistantStackExists();
            // In a multi-window environment the assistant might not be fullscreen
            assumeTrue(mDefaultWindowingMode == WINDOWING_MODE_FULLSCREEN);
            assertTrue("Expected assistant stack to be fullscreen",
                    mWmState.getRootTaskByActivityType(
                            ACTIVITY_TYPE_ASSISTANT).isFullscreen());
        }
    }

    @Test
    public void testAssistantStackZOrder() throws Exception {
        assumeTrue(assistantRunsOnPrimaryDisplay());
        assumeTrue(supportsPip());
        assumeTrue(supportsSplitScreenMultiWindow());

        // Launch a pinned stack task
        launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
        waitForValidStateWithActivityTypeAndWindowingMode(
                PIP_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_PINNED);
        mWmState.assertContainsStack("Must contain pinned stack.",
                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);

        // Dock a task
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));

        // Enable the assistant and launch an assistant activity, ensure it is on top
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION);
            waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();

            mWmState.assertFrontStack("Pinned stack should be on top.",
                    WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
            mWmState.assertFocusedRootTask("Assistant stack should be focused.",
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
        }
    }

    @Test
    public void testAssistantStackLaunchNewTask() throws Exception {
        assertAssistantStackCanLaunchAndReturnFromNewTask(mDefaultWindowingMode);
    }

    @Test
    @Ignore("b/77272253#comment10")
    public void testAssistantStackLaunchNewTaskWithDockedStack() throws Exception {
        assumeTrue(assistantRunsOnPrimaryDisplay());
        assumeTrue(supportsSplitScreenMultiWindow());

        // Dock a task
        launchActivitiesInSplitScreen(
                getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
                getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));

        //assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
    }

    private void assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)
            throws Exception {
        // Enable the assistant and launch an assistant activity which will launch a new task
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK, mAssistantDisplayId,
                    extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)),
                    extraString(EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId)));
            // Ensure that the fullscreen stack is on top and the test activity is now visible
            waitForValidStateWithActivityTypeAndWindowingMode(
                    TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
        }

        if (isAssistantOnTopOfDream()) {
            // If the assistant is configured to be always-on-top, then the new task should have
            // been started behind it and the assistant stack should still be on top.
            mWmState.assertFocusedActivity(
                    "AssistantActivity should be focused", ASSISTANT_ACTIVITY);
            mWmState.assertFrontStackActivityType(
                    "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
            mWmState.assertFocusedRootTask("Assistant stack should be focused.",
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
        } else {
            mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
            mWmState.assertFrontStack("TestActivity stack should be on top.",
                    expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
            mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
                    expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
        }

        // Now, tell it to finish itself and ensure that the assistant stack is brought back forward
        mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
        mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
        mWmState.assertFrontStackActivityType(
                "Assistant stack should be on top.", ACTIVITY_TYPE_ASSISTANT);
        mWmState.assertFocusedRootTask("Assistant stack should be focused.",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    }

    @Test
    public void testAssistantStackFinishToPreviousApp() throws Exception {
        // If the Assistant is configured to be always-on-top, then the assistant activity
        // started in setUp() will not allow any other activities to start. Therefore we should
        // remove it before launching a fullscreen activity.
        if (isAssistantOnTopOfDream()) {
            removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
        }

        // Launch an assistant activity on top of an existing fullscreen activity, and ensure that
        // the fullscreen activity is still visible and on top after the assistant activity finishes
        launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_FINISH_SELF, "true"));
            mWmState.waitFor((amState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
                    getActivityName(ASSISTANT_ACTIVITY) + " finished");
        }
        waitForValidStateWithActivityTypeAndWindowingMode(
                TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
        waitAndAssertTopResumedActivity(TEST_ACTIVITY, mAssistantDisplayId,
                "TestActivity should be resumed");
        mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
        mWmState.assertFrontStack("Fullscreen stack should be on top.",
                mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
        mWmState.assertFocusedRootTask("Fullscreen stack should be focused.",
                mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    public void testDisallowEnterPiPFromAssistantStack() throws Exception {
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_ENTER_PIP, "true"));
        }
        waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
        mWmState.assertDoesNotContainStack("Must not contain pinned stack.",
                WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
    }

    @Test
    public void testTranslucentAssistantActivityStackVisibility() throws Exception {
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            // Go home, launch the assistant and check to see that home is visible
            removeRootTasksInWindowingModes(WINDOWING_MODE_FULLSCREEN);
            pressHomeButton();
            resumeAppSwitches();
            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
            waitForValidStateWithActivityType(
                    TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.waitForHomeActivityVisible();
            if (hasHomeScreen()) {
                mWmState.assertHomeActivityVisible(true);
            }

            // Launch a fullscreen app and then launch the assistant and check to see that it is
            // also visible
            removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
            launchActivityOnDisplay(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
            waitForValidStateWithActivityType(
                    TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.assertVisibility(TEST_ACTIVITY, true);

            // Go home, launch assistant, launch app into fullscreen with activity present, and go
            // back.Ensure home is visible.
            removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
            pressHomeButton();
            resumeAppSwitches();
            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"),
                    extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)));
            waitForValidStateWithActivityTypeAndWindowingMode(
                    TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);

            final ComponentName homeActivity = mWmState.getHomeActivityName();
            int windowingMode = mWmState.getFocusedRootTaskWindowingMode();
            // In a multi-window environment the home activity might not be fully covered
            assumeTrue(windowingMode == WINDOWING_MODE_FULLSCREEN);
            mWmState.waitAndAssertVisibilityGone(homeActivity);
            mBroadcastActionTrigger.doAction(TEST_ACTIVITY_ACTION_FINISH_SELF);
            mWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.waitForHomeActivityVisible();
            if (hasHomeScreen()) {
                mWmState.assertHomeActivityVisible(true);
            }

            // Launch a fullscreen and docked app and then launch the assistant and check to see
            // that it
            // is also visible
            if (supportsSplitScreenMultiWindow() &&  assistantRunsOnPrimaryDisplay()) {
                removeRootTasksWithActivityTypes(ACTIVITY_TYPE_ASSISTANT);
                launchActivitiesInSplitScreen(
                        getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
                        getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY));
                launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                        extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"));
                waitForValidStateWithActivityType(
                        TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
                assertAssistantStackExists();
                mWmState.assertVisibility(DOCKED_ACTIVITY, true);
                mWmState.assertVisibility(TEST_ACTIVITY, true);
            }
        }
    }

    @Test
    public void testLaunchIntoSameTask() throws Exception {
        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            // Launch the assistant
            launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
                    mAssistantDisplayId);
            waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
            mWmState.assertFocusedRootTask("Expected assistant stack focused",
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
            final WindowManagerState amState = mWmState;
            assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
                    hasSize(1));
            final int taskId = mWmState.getTaskByActivity(ASSISTANT_ACTIVITY)
                    .mTaskId;

            // Launch a new fullscreen activity
            // Using Animation Test Activity because it is opaque on all devices.
            launchActivityOnDisplay(ANIMATION_TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN, mAssistantDisplayId);
            // Wait for animation finished.
            mWmState.waitForActivityState(ANIMATION_TEST_ACTIVITY, STATE_RESUMED);

            if (isAssistantOnTopOfDream()) {
                mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
            } else {
                mWmState.waitAndAssertVisibilityGone(ASSISTANT_ACTIVITY);
            }

            // Launch the assistant again and ensure that it goes into the same task
            launchActivityOnDisplayNoWait(LAUNCH_ASSISTANT_ACTIVITY_FROM_SESSION,
                    mAssistantDisplayId);
            waitForValidStateWithActivityType(ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.assertVisibility(ASSISTANT_ACTIVITY, true);
            mWmState.assertFocusedRootTask("Expected assistant stack focused",
                    WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
            assertThat(amState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT).getTasks(),
                    hasSize(1));
            assertEquals(taskId,
                    mWmState.getTaskByActivity(ASSISTANT_ACTIVITY).mTaskId);

        }
    }

    @Test
    public void testPinnedStackWithAssistant() throws Exception {
        assumeTrue(supportsPip());
        assumeTrue(supportsSplitScreenMultiWindow());

        try (final AssistantSession assistantSession = new AssistantSession()) {
            assistantSession.setVoiceInteractionService(ASSISTANT_VOICE_INTERACTION_SERVICE);

            // Launch a fullscreen activity and a PIP activity, then launch the assistant, and
            // ensure that the test activity is still visible
            launchActivity(TEST_ACTIVITY, WINDOWING_MODE_FULLSCREEN);
            launchActivity(PIP_ACTIVITY, extraString(EXTRA_ENTER_PIP, "true"));
            launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
                    extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, String.valueOf(true)));
            waitForValidStateWithActivityType(
                    TRANSLUCENT_ASSISTANT_ACTIVITY, ACTIVITY_TYPE_ASSISTANT);
            assertAssistantStackExists();
            mWmState.assertVisibility(TRANSLUCENT_ASSISTANT_ACTIVITY, true);
            mWmState.assertVisibility(PIP_ACTIVITY, true);
            mWmState.assertVisibility(TEST_ACTIVITY, true);

        }
    }

    private void waitForValidStateWithActivityType(ComponentName activityName, int activityType)
            throws Exception {
        mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
                .setActivityType(activityType)
                .build());
    }

    private void waitForValidStateWithActivityTypeAndWindowingMode(ComponentName activityName,
            int activityType, int windowingMode) throws Exception {
        mWmState.waitForValidState(new WaitForValidActivityState.Builder(activityName)
                .setActivityType(activityType)
                .setWindowingMode(windowingMode)
                .build());
    }

    /**
     * Asserts that the assistant stack exists.
     */
    private void assertAssistantStackExists() throws Exception {
        mWmState.assertContainsStack("Must contain assistant stack.",
                WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
    }

    // Any 2D Activity in VR mode is run on a special VR virtual display, so check if the Assistant
    // is going to run on the same display as other tasks.
    protected boolean assistantRunsOnPrimaryDisplay() {
        return mAssistantDisplayId == DEFAULT_DISPLAY;
    }

    /**
     * @return Windowing Mode from the default display
     */
    private int getDefaultDisplayWindowingMode() {
        mWmState.computeState();
        return mWmState.getDisplay(DEFAULT_DISPLAY).getWindowingMode();
    }

    /** Helper class to save, set, and restore
     * {@link Settings.Secure#VOICE_INTERACTION_SERVICE} system preference.
     */
    private static class AssistantSession extends SettingsSession<String> {
        AssistantSession() {
            super(Settings.Secure.getUriFor(Settings.Secure.VOICE_INTERACTION_SERVICE),
                    Settings.Secure::getString, Settings.Secure::putString);
        }

        void setVoiceInteractionService(ComponentName assistantName) throws Exception {
            super.set(getActivityName(assistantName));
        }
    }
}
