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

import static android.os.PowerManagerInternalProto.Wakefulness.WAKEFULNESS_ASLEEP;

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

import android.os.PowerManagerInternalProto.Wakefulness;

import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.ProtoUtils;
import com.android.compatibility.common.util.WindowManagerUtil;
import com.android.server.power.PowerManagerServiceDumpProto;
import com.android.server.power.PowerServiceSettingsAndConfigurationDumpProto;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;

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

@RunWith(DeviceJUnit4ClassRunner.class)
public class InattentiveSleepTests extends BaseHostJUnit4Test {
    private static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
    private static final String APK_NAME = "CtsInattentiveSleepTestApp.apk";

    private static final long TIME_BEFORE_WARNING_MS = 1200L;

    private static final String CMD_DUMPSYS_POWER = "dumpsys power --proto";
    private static final String WARNING_WINDOW_TOKEN_TITLE = "InattentiveSleepWarning";
    private static final String ACTIVITY_KEEP_SCREEN_ON = ".KeepScreenOnActivity";
    private static final String SERVICE_PARTIAL_WAKE_LOCK = ".PartialWakeLockService";
    private static final String CMD_START_ACTIVITY_TEMPLATE =
            "am start -W android.os.inattentivesleeptests/%s";
    private static final String CMD_START_FG_SERVICE_TEMPLATE =
            "am start-foreground-service android.os.inattentivesleeptests/%s";
    private static final String CMD_STOP_SERVICE_TEMPLATE =
            "am stop-service android.os.inattentivesleeptests/%s";

    private static final String CMD_GET_STAY_ON = "settings get global stay_on_while_plugged_in";
    private static final String CMD_PUT_STAY_ON_TEMPLATE =
            "settings put global stay_on_while_plugged_in %d";
    private static final String CMD_DISABLE_STAY_ON =
            "settings put global stay_on_while_plugged_in 0";
    private static final String CMD_ENABLE_STAY_ON =
            "settings put global stay_on_while_plugged_in 7";

    private static final String CMD_SET_TIMEOUT_TEMPLATE =
            "settings put secure attentive_timeout %d";
    private static final String CMD_DELETE_TIMEOUT_SETTING =
            "settings delete secure attentive_timeout";

    private static final String CMD_KEYEVENT_HOME = "input keyevent KEYCODE_HOME";
    private static final String CMD_KEYEVENT_WAKEUP = "input keyevent KEYCODE_WAKEUP";
    private static final String CMD_KEYEVENT_DPAD_CENTER = "input keyevent KEYCODE_DPAD_CENTER";

    // A reference to the device under test, which gives us a handle to run commands.
    private ITestDevice mDevice;

    private long mOriginalStayOnSetting;
    private long mWarningDurationConfig;

    @Before
    public synchronized void setUp() throws Exception {
        mDevice = getDevice();
        assumeTrue("Test only applicable to TVs.", hasDeviceFeature(FEATURE_LEANBACK_ONLY));

        mWarningDurationConfig = getWarningDurationConfig();
        mOriginalStayOnSetting = Long.parseLong(
                mDevice.executeShellCommand(CMD_GET_STAY_ON).trim());

        installPackage(APK_NAME);

        // Prevent the device from suspending while screen is off
        startPartialWakeLockService();

        mDevice.executeShellCommand(CMD_DISABLE_STAY_ON);
        setInattentiveSleepTimeout(TIME_BEFORE_WARNING_MS + mWarningDurationConfig);
    }

    @After
    public void tearDown() throws Exception {
        wakeUp();
        stopPartialWakeLockService();
        mDevice.executeShellCommand(
                String.format(CMD_PUT_STAY_ON_TEMPLATE, mOriginalStayOnSetting));
        mDevice.executeShellCommand(CMD_DELETE_TIMEOUT_SETTING);
    }

    private void wakeUpToHome() throws Exception {
        wakeUp();
        mDevice.executeShellCommand(CMD_KEYEVENT_HOME);
    }

    private void wakeUp() throws Exception {
        mDevice.executeShellCommand(CMD_KEYEVENT_WAKEUP);
    }

    private void startPartialWakeLockService() throws Exception {
        mDevice.executeShellCommand(
                String.format(CMD_START_FG_SERVICE_TEMPLATE, SERVICE_PARTIAL_WAKE_LOCK));
    }

    private void stopPartialWakeLockService() throws Exception {
        mDevice.executeShellCommand(
                String.format(CMD_STOP_SERVICE_TEMPLATE, SERVICE_PARTIAL_WAKE_LOCK));
    }

    private void startKeepScreenOnActivity() throws Exception {
        mDevice.executeShellCommand(
                String.format(CMD_START_ACTIVITY_TEMPLATE, ACTIVITY_KEEP_SCREEN_ON));
    }

    private void setInattentiveSleepTimeout(long timeoutMs) throws Exception {
        mDevice.executeShellCommand(String.format(CMD_SET_TIMEOUT_TEMPLATE, timeoutMs));
    }

    @Test
    public void testInattentiveSleep_noWarningIfStayOnIsEnabled() throws Exception {
        assumeTrue("Device is not powered.", getPowerManagerDump().getIsPowered());
        mDevice.executeShellCommand(CMD_ENABLE_STAY_ON);

        wakeUpToHome();
        Thread.sleep(TIME_BEFORE_WARNING_MS);
        assertWarningShown(
                "Warning was shown, although the stay-on developer option was enabled.", false);
    }

    @Test
    public void testInattentiveSleep_warningShowsBeforeSleep() throws Exception {
        wakeUpToHome();
        Thread.sleep(TIME_BEFORE_WARNING_MS);
        assertWarningShown(
                "Warning was not shown before the attentive sleep timeout expired.", true);
    }

    @Test
    public void testInattentiveSleep_keypressDismissesWarning() throws Exception {
        wakeUpToHome();
        waitUntilWarningIsShowing();
        mDevice.executeShellCommand(CMD_KEYEVENT_DPAD_CENTER);
        assertWarningShown("Warning was shown after a keypress.", false);
    }

    @Test
    public void testInattentiveSleep_warningHiddenAfterWakingUp() throws Exception {
        wakeUpToHome();
        waitUntilAsleep();
        wakeUp();
        assertWarningShown("Warning was shown after waking up.", false);
    }

    @Test
    public void testInattentiveSleep_noWarningShownIfInattentiveSleepDisabled() throws Exception {
        setInattentiveSleepTimeout(-1);
        wakeUpToHome();
        Thread.sleep(TIME_BEFORE_WARNING_MS);
        assertWarningShown(
                "Warning was shown, even though the attentive sleep timeout is disabled.", false);
    }

    @Test
    public void testInattentiveSleep_goesToSleepAfterTimeout() throws Exception {
        long minScreenOffTimeout =
                getPowerManagerDump().getSettingsAndConfiguration().getMinimumScreenOffTimeoutConfigMs();
        setInattentiveSleepTimeout(minScreenOffTimeout);
        wakeUpToHome();
        Thread.sleep(minScreenOffTimeout);
        PollingCheck.check("Expected device to be asleep after timeout", TIME_BEFORE_WARNING_MS,
                () -> getWakefulness() == WAKEFULNESS_ASLEEP);
    }

    @Test
    public void testInattentiveSleep_goesToSleepAfterTimeoutWithWakeLock() throws Exception {
        long minScreenOffTimeout =
                getPowerManagerDump().getSettingsAndConfiguration().getMinimumScreenOffTimeoutConfigMs();
        setInattentiveSleepTimeout(minScreenOffTimeout);
        wakeUpToHome();
        startKeepScreenOnActivity();
        Thread.sleep(minScreenOffTimeout);
        PollingCheck.check("Expected device to be asleep after timeout", 1000,
                () -> getWakefulness() == WAKEFULNESS_ASLEEP);
    }

    @Test
    public void testInattentiveSleep_showsSleepWarningWithWakeLock() throws Exception {
        wakeUpToHome();
        startKeepScreenOnActivity();
        Thread.sleep(TIME_BEFORE_WARNING_MS);
        assertWarningShown(
                "Warning was not shown before the attentive sleep timeout expired.", true);
    }

    @Test
    public void testInattentiveSleep_warningTiming() throws Exception {
        setInattentiveSleepTimeout(5000 + mWarningDurationConfig);

        long eps = 1000;
        wakeUpToHome();

        long start = System.currentTimeMillis();
        waitUntilWarningIsNotShowing(1000);
        waitUntilWarningIsShowing(5000);
        long warningShown = System.currentTimeMillis();

        long actualTimeToWarningShown = warningShown - start;
        assertTrue("Warning was shown at unexpected time, after " + actualTimeToWarningShown + "ms",
                Math.abs(actualTimeToWarningShown - 5000) <= eps);

        long sleepTime = warningShown + mWarningDurationConfig - eps;
        while (System.currentTimeMillis() < sleepTime) {
            assertTrue("Warning dismissed early", isWarningShown());
            Thread.sleep(50);
        }
    }

    private Wakefulness getWakefulness() throws Exception {
        return getPowerManagerDump().getWakefulness();
    }

    private PowerManagerServiceDumpProto getPowerManagerDump() throws Exception {
        return ProtoUtils.getProto(getDevice(), PowerManagerServiceDumpProto.parser(),
                CMD_DUMPSYS_POWER);
    }

    private long getWarningDurationConfig() throws Exception {
        PowerServiceSettingsAndConfigurationDumpProto settingsAndConfiguration =
                getPowerManagerDump().getSettingsAndConfiguration();
        return settingsAndConfiguration.getAttentiveWarningDurationConfigMs();
    }

    private void assertWarningShown(String message, boolean expected) throws Exception {
        PollingCheck.check(message, TIME_BEFORE_WARNING_MS + 500,
                () -> isWarningShown() == expected);
    }

    private boolean isWarningShown() throws Exception {
        return WindowManagerUtil.hasWindowWithTitle(getDevice(), WARNING_WINDOW_TOKEN_TITLE);
    }

    private void waitUntilAsleep() throws Exception {
        PollingCheck.waitFor(TIME_BEFORE_WARNING_MS + mWarningDurationConfig + 2000,
                () -> getWakefulness() == WAKEFULNESS_ASLEEP);
    }

    private void waitUntilWarningIsShowing() throws Exception {
        waitUntilWarningIsShowing(TIME_BEFORE_WARNING_MS + 1000);
    }

    private void waitUntilWarningIsShowing(long timeout) throws Exception {
        PollingCheck.waitFor(timeout, this::isWarningShown);
    }

    private void waitUntilWarningIsNotShowing(long timeout) throws Exception {
        PollingCheck.waitFor(timeout, () -> !isWarningShown());
    }
}
