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

import static android.server.wm.WindowManagerState.STATE_STOPPED;
import static android.server.wm.WindowManagerState.TRANSIT_ACTIVITY_OPEN;
import static android.server.wm.WindowManagerState.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.server.wm.WindowManagerState.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
import static android.server.wm.WindowManagerState.TRANSIT_KEYGUARD_OCCLUDE;
import static android.server.wm.WindowManagerState.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.server.wm.app.Components.DISABLE_PREVIEW_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY;
import static android.server.wm.app.Components.SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY;
import static android.server.wm.app.Components.WALLPAPAER_ACTIVITY;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import android.platform.test.annotations.Presubmit;

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

/**
 * Build/Install/Run:
 *     atest CtsWindowManagerDeviceTestCases:KeyguardTransitionTests
 */
@Presubmit
@android.server.wm.annotation.Group2
public class KeyguardTransitionTests extends ActivityManagerTestBase {

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();

        assumeTrue(supportsInsecureLock());
        assumeFalse(isUiModeLockedToVrHeadset());
    }

    @Test
    public void testUnlock() {
        List<String> expectedTransitionList = Arrays.asList(TRANSIT_KEYGUARD_GOING_AWAY,
                TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        launchActivity(DISABLE_PREVIEW_ACTIVITY);
        lockScreenSession.gotoKeyguard().unlockDevice();
        mWmState.computeState(DISABLE_PREVIEW_ACTIVITY);
        // The AOSP flow is checking if the current transit is TRANSIT_KEYGUARD_GOING_AWAY and
        // if the visible apps have FLAG_SHOW_WALLPAPER and if both conditions are true the transit
        // will be changed to TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER. For multiple screen devices,
        // both conditions are true, because the launcher is visible and has this flag.
        assertTrue("Picked wrong transition",
                expectedTransitionList.contains(mWmState.getDefaultDisplayLastTransition()));
    }

    @Test
    public void testUnlockWallpaper() {
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        launchActivity(WALLPAPAER_ACTIVITY);
        lockScreenSession.gotoKeyguard().unlockDevice();
        mWmState.computeState(WALLPAPAER_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
                mWmState.getDefaultDisplayLastTransition());
    }

    @Test
    public void testOcclude() {
        createManagedLockScreenSession().gotoKeyguard();
        launchActivity(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
        mWmState.computeState(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_OCCLUDE,
                mWmState.getDefaultDisplayLastTransition());
    }

    @Test
    public void testUnocclude() {
        createManagedLockScreenSession().gotoKeyguard();
        launchActivity(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
        launchActivity(DISABLE_PREVIEW_ACTIVITY);
        mWmState.waitForKeyguardShowingAndNotOccluded();
        mWmState.computeState();
        assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_UNOCCLUDE,
                mWmState.getDefaultDisplayLastTransition());
    }

    @Test
    public void testNewActivityDuringOccluded() {
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        launchActivity(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
        lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_NO_PREVIEW_ACTIVITY);
        launchActivity(SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
        mWmState.computeState(SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_ACTIVITY_OPEN,
                mWmState.getDefaultDisplayLastTransition());
    }

    @Test
    public void testOccludeManifestAttr() {
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        lockScreenSession.gotoKeyguard();
        separateTestJournal();
        launchActivity(SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY);
        mWmState.computeState(SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_OCCLUDE,
                mWmState.getDefaultDisplayLastTransition());
        assertSingleLaunch(SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY);
    }

    @Test
    public void testOccludeAttrRemove() {
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        lockScreenSession.gotoKeyguard();
        separateTestJournal();
        launchActivity(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY);
        mWmState.computeState(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_KEYGUARD_OCCLUDE,
                mWmState.getDefaultDisplayLastTransition());
        assertSingleLaunch(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY);

        // Waiting for the standard keyguard since
        // {@link SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY} called
        // {@link Activity#showWhenLocked(boolean)} and removed the attribute.
        lockScreenSession.gotoKeyguard();
        separateTestJournal();
        // Waiting for {@link SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY} stopped since it
        // already lost show-when-locked attribute.
        launchActivityNoWait(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY);
        mWmState.waitForActivityState(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY,
                STATE_STOPPED);
        assertSingleStartAndStop(SHOW_WHEN_LOCKED_ATTR_REMOVE_ATTR_NO_PREVIEW_ACTIVITY);
    }

    @Test
    public void testNewActivityDuringOccludedWithAttr() {
        final LockScreenSession lockScreenSession = createManagedLockScreenSession();
        launchActivity(SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY);
        lockScreenSession.gotoKeyguard(SHOW_WHEN_LOCKED_ATTR_NO_PREVIEW_ACTIVITY);
        launchActivity(SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
        mWmState.computeState(SHOW_WHEN_LOCKED_WITH_DIALOG_NO_PREVIEW_ACTIVITY);
        assertEquals("Picked wrong transition", TRANSIT_ACTIVITY_OPEN,
                mWmState.getDefaultDisplayLastTransition());
    }
}
