/*
 * 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.jobscheduler.cts;


import android.Manifest;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.content.res.Resources;

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

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Schedules jobs with the {@link android.app.job.JobScheduler} that have battery constraints.
 */
@TargetApi(26)
public class BatteryConstraintTest extends ConstraintTest {
    private static final String TAG = "BatteryConstraintTest";

    /** Unique identifier for the job scheduled by this suite of tests. */
    public static final int BATTERY_JOB_ID = BatteryConstraintTest.class.hashCode();

    private JobInfo.Builder mBuilder;
	private int mLowBatteryWarningLevel = 15;
    /**
     * Record of the previous state of power save mode trigger level to reset it after the test
     * finishes.
     */
    private int mPreviousLowPowerTriggerLevel;

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

        mLowBatteryWarningLevel = Resources.getSystem().getInteger(
                     Resources.getSystem().getIdentifier(
                             "config_lowBatteryWarningLevel", "integer", "android"));
        // Disable power save mode as some devices may turn off Android when power save mode is
        // enabled, causing the test to fail.
        mPreviousLowPowerTriggerLevel = Settings.Global.getInt(getContext().getContentResolver(),
                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1);
        Settings.Global.putInt(getContext().getContentResolver(),
                Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);

        mBuilder = new JobInfo.Builder(BATTERY_JOB_ID, kJobServiceComponent);
        SystemUtil.runShellCommand(getInstrumentation(), "cmd jobscheduler monitor-battery on");
    }

    @Override
    public void tearDown() throws Exception {
        mJobScheduler.cancel(BATTERY_JOB_ID);
        // Put battery service back in to normal operation.
        SystemUtil.runShellCommand(getInstrumentation(), "cmd jobscheduler monitor-battery off");
        SystemUtil.runShellCommand(getInstrumentation(), "cmd battery reset");

        // Reset power save mode to its previous state.
        if (mPreviousLowPowerTriggerLevel == -1) {
            Settings.Global.putString(getContext().getContentResolver(),
                    Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, null);
        } else {
            Settings.Global.putInt(getContext().getContentResolver(),
                    Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, mPreviousLowPowerTriggerLevel);
        }
    }

    void setBatteryState(boolean plugged, int level) throws Exception {
        if (plugged) {
            SystemUtil.runShellCommand(getInstrumentation(), "cmd battery set ac 1");
        } else {
            SystemUtil.runShellCommand(getInstrumentation(), "cmd battery unplug");
        }
        int seq = Integer.parseInt(SystemUtil.runShellCommand(getInstrumentation(),
                "cmd battery set -f level " + level).trim());
        long startTime = SystemClock.elapsedRealtime();

        // Wait for the battery update to be processed by job scheduler before proceeding.
        int curSeq;
        boolean curCharging;
        do {
            Thread.sleep(50);
            curSeq = Integer.parseInt(SystemUtil.runShellCommand(getInstrumentation(),
                    "cmd jobscheduler get-battery-seq").trim());
            // The job scheduler actually looks at the charging/discharging state,
            // which is currently determined by battery stats in response to the low-level
            // plugged/unplugged events.  So we can get this updated after the last seq
            // is received, so we need to make sure that has correctly changed.
            curCharging = Boolean.parseBoolean(SystemUtil.runShellCommand(getInstrumentation(),
                    "cmd jobscheduler get-battery-charging").trim());
            if (curSeq == seq && curCharging == plugged) {
                return;
            }
        } while ((SystemClock.elapsedRealtime() - startTime) < 5000);

        fail("Timed out waiting for job scheduler: expected seq=" + seq + ", cur=" + curSeq
                + ", plugged=" + plugged + " curCharging=" + curCharging);
    }

    void verifyChargingState(boolean charging) throws Exception {
        boolean curCharging = Boolean.parseBoolean(SystemUtil.runShellCommand(getInstrumentation(),
                "cmd jobscheduler get-battery-charging").trim());
        assertEquals(charging, curCharging);
    }

    void verifyBatteryNotLowState(boolean notLow) throws Exception {
        boolean curNotLow = Boolean.parseBoolean(SystemUtil.runShellCommand(getInstrumentation(),
                "cmd jobscheduler get-battery-not-low").trim());
        assertEquals(notLow, curNotLow);
        IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryState = getContext().registerReceiver(null, filter);
        assertEquals(notLow,
                !batteryState.getBooleanExtra(BatteryManager.EXTRA_BATTERY_LOW, notLow));
    }

    String getJobState() throws Exception {
        return getJobState(BATTERY_JOB_ID);
    }

    void assertJobReady() throws Exception {
        assertJobReady(BATTERY_JOB_ID);
    }

    void assertJobWaiting() throws Exception {
        assertJobWaiting(BATTERY_JOB_ID);
    }

    void assertJobNotReady() throws Exception {
        assertJobNotReady(BATTERY_JOB_ID);
    }

    static void waitFor(long waitMillis) throws Exception {
        final long deadline = SystemClock.uptimeMillis() + waitMillis;
        do {
            Thread.sleep(500L);
        } while (SystemClock.uptimeMillis() < deadline);
    }

    // --------------------------------------------------------------------------------------------
    // Positives - schedule jobs under conditions that require them to pass.
    // --------------------------------------------------------------------------------------------

    /**
     * Schedule a job that requires the device is charging, when the battery reports it is
     * plugged in.
     */
    public void testChargingConstraintExecutes() throws Exception {
        setBatteryState(true, 100);
        verifyChargingState(true);

        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedWaitForRun();
        mJobScheduler.schedule(mBuilder.setRequiresCharging(true).build());
        assertJobReady();
        kTestEnvironment.readyToRun();

        assertTrue("Job with charging constraint did not fire on power.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule a job that requires the device is not critical, when the battery reports it is
     * plugged in.
     */
    public void testBatteryNotLowConstraintExecutes_withPower() throws Exception {
        setBatteryState(true, 100);
        waitFor(2_000);
        verifyChargingState(true);
        verifyBatteryNotLowState(true);

        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedWaitForRun();
        mJobScheduler.schedule(mBuilder.setRequiresBatteryNotLow(true).build());
        assertJobReady();
        kTestEnvironment.readyToRun();

        assertTrue("Job with battery not low constraint did not fire on power.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule a job that requires the device is not critical, when the battery reports it is
     * not plugged in but has sufficient power.
     */
    public void testBatteryNotLowConstraintExecutes_withoutPower() throws Exception {
        setBatteryState(false, 100);
        waitFor(2_000);
        verifyChargingState(false);
        verifyBatteryNotLowState(true);

        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedWaitForRun();
        mJobScheduler.schedule(mBuilder.setRequiresBatteryNotLow(true).build());
        assertJobReady();
        kTestEnvironment.readyToRun();

        assertTrue("Job with battery not low constraint did not fire on power.",
                kTestEnvironment.awaitExecution());
    }

    // --------------------------------------------------------------------------------------------
    // Negatives - schedule jobs under conditions that require that they fail.
    // --------------------------------------------------------------------------------------------

    /**
     * Schedule a job that requires the device is charging, and assert if failed when
     * the device is not on power.
     */
    public void testChargingConstraintFails() throws Exception {
        setBatteryState(false, 100);
        verifyChargingState(false);

        kTestEnvironment.setExpectedExecutions(0);
        kTestEnvironment.setExpectedWaitForRun();
        mJobScheduler.schedule(mBuilder.setRequiresCharging(true).build());
        assertJobWaiting();
        assertJobNotReady();
        kTestEnvironment.readyToRun();

        assertFalse("Job with charging constraint fired while not on power.",
                kTestEnvironment.awaitExecution(250));
        assertJobWaiting();
        assertJobNotReady();

        // Ensure the job runs once the device is plugged in.
        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedWaitForRun();
        kTestEnvironment.setContinueAfterStart();
        setBatteryState(true, 100);
        verifyChargingState(true);
        kTestEnvironment.setExpectedStopped();
        assertJobReady();
        kTestEnvironment.readyToRun();
        assertTrue("Job with charging constraint did not fire on power.",
                kTestEnvironment.awaitExecution());

        // And check that the job is stopped if the device is unplugged while it is running.
        setBatteryState(false, 100);
        verifyChargingState(false);
        assertTrue("Job with charging constraint did not stop when power removed.",
                kTestEnvironment.awaitStopped());
    }

    /**
     * Schedule a job that requires the device is not critical, and assert it failed when
     * the battery level is critical and not on power.
     */
    public void testBatteryNotLowConstraintFails_withoutPower() throws Exception {
        setBatteryState(false, mLowBatteryWarningLevel);
        // setBatteryState() waited for the charging/not-charging state to formally settle,
        // but battery level reporting lags behind that.  wait a moment to let that happen
        // before proceeding.
        waitFor(2_000);
        verifyChargingState(false);
        verifyBatteryNotLowState(false);

        kTestEnvironment.setExpectedExecutions(0);
        kTestEnvironment.setExpectedWaitForRun();
        mJobScheduler.schedule(mBuilder.setRequiresBatteryNotLow(true).build());
        assertJobWaiting();
        assertJobNotReady();
        kTestEnvironment.readyToRun();

        assertFalse("Job with battery not low constraint fired while level critical.",
                kTestEnvironment.awaitExecution(250));
        assertJobWaiting();
        assertJobNotReady();

        // Ensure the job runs once the device's battery level is not low.
        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedWaitForRun();
        kTestEnvironment.setContinueAfterStart();
        setBatteryState(false, 50);
        waitFor(2_000);
        verifyChargingState(false);
        verifyBatteryNotLowState(true);
        kTestEnvironment.setExpectedStopped();
        assertJobReady();
        kTestEnvironment.readyToRun();
        assertTrue("Job with not low constraint did not fire when charge increased.",
                kTestEnvironment.awaitExecution());

        // And check that the job is stopped if battery goes low again.
        setBatteryState(false, mLowBatteryWarningLevel);
        setBatteryState(false, mLowBatteryWarningLevel - 1);
        waitFor(2_000);
        verifyChargingState(false);
        verifyBatteryNotLowState(false);
        assertTrue("Job with not low constraint did not stop when battery went low.",
                kTestEnvironment.awaitStopped());
    }
}
