/*
 * Copyright (C) 2014 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 static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

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

import android.Manifest;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.platform.test.annotations.RequiresDevice;
import android.provider.Settings;
import android.util.Log;

import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
import com.android.compatibility.common.util.CallbackAsserter;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;

import junit.framework.AssertionFailedError;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Schedules jobs with the {@link android.app.job.JobScheduler} that have network connectivity
 * constraints.
 * Requires manipulating the {@link android.net.wifi.WifiManager} to ensure an unmetered network.
 * Similarly, requires that the phone be connected to a wifi hotspot, or else the test will fail.
 */
@TargetApi(21)
@RequiresDevice // Emulators don't always have access to wifi/network
public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
    private static final String TAG = "ConnectivityConstraintTest";
    private static final String RESTRICT_BACKGROUND_GET_CMD =
            "cmd netpolicy get restrict-background";
    private static final String RESTRICT_BACKGROUND_ON_CMD =
            "cmd netpolicy set restrict-background true";
    private static final String RESTRICT_BACKGROUND_OFF_CMD =
            "cmd netpolicy set restrict-background false";

    /** Unique identifier for the job scheduled by this suite of tests. */
    public static final int CONNECTIVITY_JOB_ID = ConnectivityConstraintTest.class.hashCode();
    /** Wait this long before timing out the test. */
    private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds.

    private WifiManager mWifiManager;
    private ConnectivityManager mCm;

    /** Whether the device running these tests supports WiFi. */
    private boolean mHasWifi;
    /** Whether the device running these tests supports telephony. */
    private boolean mHasTelephony;
    /** Whether the device running these tests supports ethernet. */
    private boolean mHasEthernet;
    /** Track whether WiFi was enabled in case we turn it off. */
    private boolean mInitialWiFiState;
    /** Track initial WiFi metered state. */
    private String mInitialWiFiMeteredState;
    private String mInitialWiFiSSID;
    /** Track whether restrict background policy was enabled in case we turn it off. */
    private boolean mInitialRestrictBackground;
    /** Track whether airplane mode was enabled in case we toggle it. */
    private boolean mInitialAirplaneMode;
    /** Track whether the restricted bucket was enabled in case we toggle it. */
    private String mInitialRestrictedBucketEnabled;
    /** Track the location mode in case we change it. */
    private String mInitialLocationMode;

    private JobInfo.Builder mBuilder;

    private TestAppInterface mTestAppInterface;

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

        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
        mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);

        PackageManager packageManager = mContext.getPackageManager();
        mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
        mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
        mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
        mBuilder = new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);

        mInitialLocationMode = Settings.Secure.getString(mContext.getContentResolver(),
                Settings.Secure.LOCATION_MODE);
        if (mHasWifi) {
            mInitialWiFiState = mWifiManager.isWifiEnabled();
            ensureSavedWifiNetwork(mWifiManager);
            setWifiState(true, mCm, mWifiManager);
            mInitialWiFiSSID = getWifiSSID();
            mInitialWiFiMeteredState = getWifiMeteredStatus(mInitialWiFiSSID);
        }
        mInitialRestrictBackground = SystemUtil
                .runShellCommand(getInstrumentation(), RESTRICT_BACKGROUND_GET_CMD)
                .contains("enabled");
        mInitialRestrictedBucketEnabled = Settings.Global.getString(mContext.getContentResolver(),
                Settings.Global.ENABLE_RESTRICTED_BUCKET);
        setDataSaverEnabled(false);
        mInitialAirplaneMode = isAirplaneModeOn();
        setAirplaneMode(false);
        // Force the test app out of the never bucket.
        SystemUtil.runShellCommand("am set-standby-bucket "
                + TestAppInterface.TEST_APP_PACKAGE + " rare");
    }

    @Override
    public void tearDown() throws Exception {
        if (mTestAppInterface != null) {
            mTestAppInterface.cleanup();
        }
        mJobScheduler.cancel(CONNECTIVITY_JOB_ID);

        BatteryUtils.runDumpsysBatteryReset();

        // Restore initial restrict background data usage policy
        setDataSaverEnabled(mInitialRestrictBackground);

        // Restore initial restricted bucket setting.
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ENABLE_RESTRICTED_BUCKET, mInitialRestrictedBucketEnabled);

        // Ensure that we leave WiFi in its previous state.
        if (mHasWifi) {
            setWifiMeteredState(mInitialWiFiSSID, mInitialWiFiMeteredState);
            if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
                try {
                    setWifiState(mInitialWiFiState, mCm, mWifiManager);
                } catch (AssertionFailedError e) {
                    // Don't fail the test just because wifi state wasn't set in tearDown.
                    Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
                }
            }
        }

        // Restore initial airplane mode status. Do it after setting wifi in case wifi was
        // originally metered.
        setAirplaneMode(mInitialAirplaneMode);

        setLocationMode(mInitialLocationMode);

        super.tearDown();
    }

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

    /**
     * Schedule a job that requires a WiFi connection, and assert that it executes when the device
     * is connected to WiFi. This will fail if a wifi connection is unavailable.
     */
    public void testUnmeteredConstraintExecutes_withWifi() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        setWifiMeteredState(false);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

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

    /**
     * Schedule a job with a connectivity constraint, and ensure that it executes on WiFi.
     */
    public void testConnectivityConstraintExecutes_withWifi() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        setWifiMeteredState(false);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

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

    /**
     * Schedule a job with a generic connectivity constraint, and ensure that it executes on WiFi,
     * even with Data Saver on.
     */
    public void testConnectivityConstraintExecutes_withWifi_DataSaverOn() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        setWifiMeteredState(false);
        setDataSaverEnabled(true);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job with connectivity constraint did not fire on unmetered WiFi.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule a job with a generic connectivity constraint, and ensure that it executes
     * on a cellular data connection.
     */
    public void testConnectivityConstraintExecutes_withMobile() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            return;
        }
        disconnectWifiToConnectToMobile();

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

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

    /**
     * Schedule a job with a generic connectivity constraint, and ensure that it executes
     * on a metered wifi connection.
     */
    public void testConnectivityConstraintExecutes_withMeteredWifi() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (!mHasWifi) {
            return;
        }
        setWifiMeteredState(true);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job with connectivity constraint did not fire on metered wifi.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule a job with a generic connectivity constraint, and ensure that it isn't stopped when
     * the device transitions to WiFi.
     */
    public void testConnectivityConstraintExecutes_transitionNetworks() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        if (!checkDeviceSupportsMobileData()) {
            return;
        }
        disconnectWifiToConnectToMobile();

        kTestEnvironment.setExpectedExecutions(1);
        kTestEnvironment.setExpectedStopped();
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job with connectivity constraint did not fire on mobile.",
                kTestEnvironment.awaitExecution());

        connectToWifi();
        assertFalse(
                "Job with connectivity constraint was stopped when network transitioned to WiFi.",
                kTestEnvironment.awaitStopped());
    }

    /**
     * Schedule a job with a metered connectivity constraint, and ensure that it executes
     * on a mobile data connection.
     */
    public void testConnectivityConstraintExecutes_metered_mobile() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            return;
        }
        disconnectWifiToConnectToMobile();

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED)
                        .build());

        runSatisfiedJob(CONNECTIVITY_JOB_ID);
        assertTrue("Job with metered connectivity constraint did not fire on mobile.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule a job with a metered connectivity constraint, and ensure that it executes
     * on a mobile data connection.
     */
    public void testConnectivityConstraintExecutes_metered_Wifi() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (!mHasWifi) {
            return;
        }
        setWifiMeteredState(true);


        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED).build());

        // Since we equate "metered" to "cellular", the job shouldn't start.
        runSatisfiedJob(CONNECTIVITY_JOB_ID);
        assertTrue("Job with metered connectivity constraint fired on a metered wifi network.",
                kTestEnvironment.awaitTimeout());
    }

    /**
     * Schedule a job with a cellular connectivity constraint, and ensure that it executes
     * on a mobile data connection and is not stopped when Data Saver is turned on because the app
     * is in the foreground.
     */
    public void testCellularConstraintExecutedAndStopped_Foreground() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            // No mobile or wifi.
            return;
        }

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);
        mTestAppInterface.startAndKeepTestActivity();
        toggleScreenOn(true);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_ANY, false);

        mTestAppInterface.runSatisfiedJob();
        assertTrue("Job with metered connectivity constraint did not fire on a metered network.",
                mTestAppInterface.awaitJobStart(30_000));

        setDataSaverEnabled(true);
        assertFalse(
                "Job with metered connectivity constraint for foreground app was stopped when"
                        + " Data Saver was turned on.",
                mTestAppInterface.awaitJobStop(30_000));
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when if an app is idle.
     */
    public void testExpeditedJobExecutes_IdleApp() throws Exception {
        if (!AppStandbyUtils.isAppStandbyEnabled()) {
            Log.d(TAG, "App standby not enabled");
            return;
        }
        // We're skipping this test because we can't make the ethernet connection metered.
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered network.");
            return;
        }

        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ENABLE_RESTRICTED_BUCKET, "1");
        mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
        SystemUtil.runShellCommand("am set-standby-bucket "
                + kJobServiceComponent.getPackageName() + " restricted");
        BatteryUtils.runDumpsysBatteryUnplug();

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .setExpedited(true)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Expedited job requiring connectivity did not fire when app was idle.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when Battery Saver is on.
     */
    public void testExpeditedJobExecutes_BatterySaverOn() throws Exception {
        if (!BatteryUtils.isBatterySaverSupported()) {
            Log.d(TAG, "Skipping test that requires battery saver support");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered.");
            return;
        }

        BatteryUtils.runDumpsysBatteryUnplug();
        BatteryUtils.enableBatterySaver(true);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .setExpedited(true)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue(
                "Expedited job requiring connectivity did not fire with Battery Saver on.",
                kTestEnvironment.awaitExecution());
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when Data Saver is on and the device is not connected to WiFi.
     */
    public void testFgExpeditedJobBypassesDataSaver() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered network.");
            return;
        }
        setDataSaverEnabled(true);

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);
        mTestAppInterface.startAndKeepTestActivity();

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_ANY, true);
        mTestAppInterface.runSatisfiedJob();

        assertTrue(
                "FG expedited job requiring metered connectivity did not fire with Data Saver on.",
                mTestAppInterface.awaitJobStart(DEFAULT_TIMEOUT_MILLIS));
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when multiple firewalls are active.
     */
    public void testExpeditedJobBypassesSimultaneousFirewalls_noDataSaver() throws Exception {
        if (!BatteryUtils.isBatterySaverSupported()) {
            Log.d(TAG, "Skipping test that requires battery saver support");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered network.");
            return;
        }
        if (!AppStandbyUtils.isAppStandbyEnabled()) {
            Log.d(TAG, "App standby not enabled");
            return;
        }

        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ENABLE_RESTRICTED_BUCKET, "1");
        mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
        SystemUtil.runShellCommand("am set-standby-bucket "
                + kJobServiceComponent.getPackageName() + " restricted");
        BatteryUtils.runDumpsysBatteryUnplug();
        BatteryUtils.enableBatterySaver(true);
        setDataSaverEnabled(false);

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                        .setExpedited(true)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Expedited job requiring connectivity did not fire with multiple firewalls.",
                kTestEnvironment.awaitExecution());
    }

    // --------------------------------------------------------------------------------------------
    // Positives & Negatives - schedule jobs under conditions that require that pass initially and
    // then fail with a constraint change.
    // --------------------------------------------------------------------------------------------

    /**
     * Schedule a job with a cellular connectivity constraint, and ensure that it executes
     * on a mobile data connection and is stopped when Data Saver is turned on.
     */
    public void testCellularConstraintExecutedAndStopped() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            return;
        }
        disconnectWifiToConnectToMobile();

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_CELLULAR, false);

        mTestAppInterface.runSatisfiedJob();
        assertTrue("Job with cellular constraint did not fire on mobile.",
                mTestAppInterface.awaitJobStart(DEFAULT_TIMEOUT_MILLIS));

        setDataSaverEnabled(true);
        assertTrue(
                "Job with cellular constraint was not stopped when Data Saver was turned on.",
                mTestAppInterface.awaitJobStop(DEFAULT_TIMEOUT_MILLIS));
    }

    public void testJobParametersNetwork() throws Exception {
        setAirplaneMode(false);

        // Everything good.
        final NetworkRequest nr = new NetworkRequest.Builder()
                .addCapability(NET_CAPABILITY_INTERNET)
                .addCapability(NET_CAPABILITY_VALIDATED)
                .build();
        JobInfo ji = mBuilder.setRequiredNetwork(nr).build();

        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(ji);
        runSatisfiedJob(CONNECTIVITY_JOB_ID);
        assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution());

        JobParameters params = kTestEnvironment.getLastStartJobParameters();
        assertNotNull(params.getNetwork());
        final NetworkCapabilities capabilities =
                getContext().getSystemService(ConnectivityManager.class)
                        .getNetworkCapabilities(params.getNetwork());
        assertTrue(nr.canBeSatisfiedBy(capabilities));

        if (!hasEthernetConnection()) {
            // Deadline passed with no network satisfied.
            setAirplaneMode(true);
            ji = mBuilder
                    .setRequiredNetwork(nr)
                    .setOverrideDeadline(0)
                    .build();

            kTestEnvironment.setExpectedExecutions(1);
            mJobScheduler.schedule(ji);
            runSatisfiedJob(CONNECTIVITY_JOB_ID);
            assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution());

            params = kTestEnvironment.getLastStartJobParameters();
            assertNull(params.getNetwork());
        }

        // No network requested
        setAirplaneMode(false);
        ji = mBuilder.setRequiredNetwork(null).build();
        kTestEnvironment.setExpectedExecutions(1);
        mJobScheduler.schedule(ji);
        runSatisfiedJob(CONNECTIVITY_JOB_ID);
        assertTrue("Job didn't fire immediately", kTestEnvironment.awaitExecution());

        params = kTestEnvironment.getLastStartJobParameters();
        assertNull(params.getNetwork());
    }

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

    /**
     * Schedule a job that requires a WiFi connection, and assert that it fails when the device is
     * connected to a cellular provider.
     * This test assumes that if the device supports a mobile data connection, then this connection
     * will be available.
     */
    public void testUnmeteredConstraintFails_withMobile() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            return;
        }
        disconnectWifiToConnectToMobile();

        kTestEnvironment.setExpectedExecutions(0);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job requiring unmetered connectivity still executed on mobile.",
                kTestEnvironment.awaitTimeout());
    }

    /**
     * Schedule a job that requires a metered connection, and verify that it does not run when
     * the device is not connected to WiFi and Data Saver is on.
     */
    public void testMeteredConstraintFails_withMobile_DataSaverOn() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            Log.d(TAG, "Skipping test that requires the device be mobile data enabled.");
            return;
        }
        disconnectWifiToConnectToMobile();
        setDataSaverEnabled(true);

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_CELLULAR, false);
        mTestAppInterface.runSatisfiedJob();

        assertFalse("Job requiring cellular connectivity executed with Data Saver on",
                mTestAppInterface.awaitJobStop(DEFAULT_TIMEOUT_MILLIS));
    }

    /**
     * Schedule a job that requires a metered connection, and verify that it does not run when
     * the device is not connected to WiFi and Data Saver is on.
     */
    public void testEJMeteredConstraintFails_withMobile_DataSaverOn() throws Exception {
        if (!checkDeviceSupportsMobileData()) {
            Log.d(TAG, "Skipping test that requires the device be mobile data enabled.");
            return;
        }
        disconnectWifiToConnectToMobile();
        setDataSaverEnabled(true);

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_CELLULAR, true);
        mTestAppInterface.runSatisfiedJob();

        assertFalse("BG expedited job requiring cellular connectivity executed with Data Saver on",
                mTestAppInterface.awaitJobStop(DEFAULT_TIMEOUT_MILLIS));
    }

    /**
     * Schedule a job that requires a metered connection, and verify that it does not run when
     * the device is connected to an unmetered WiFi provider.
     * This test assumes that if the device supports a mobile data connection, then this connection
     * will be available.
     */
    public void testMeteredConstraintFails_withWiFi() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        if (!checkDeviceSupportsMobileData()) {
            Log.d(TAG, "Skipping test that requires the device be mobile data enabled.");
            return;
        }
        setWifiMeteredState(false);

        kTestEnvironment.setExpectedExecutions(0);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job requiring metered connectivity still executed on WiFi.",
                kTestEnvironment.awaitTimeout());
    }

    /**
     * Schedule a job that requires an unmetered connection, and verify that it does not run when
     * the device is connected to a metered WiFi provider.
     */
    public void testUnmeteredConstraintFails_withMeteredWiFi() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        setWifiMeteredState(true);

        kTestEnvironment.setExpectedExecutions(0);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                        .build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job requiring unmetered connectivity still executed on metered WiFi.",
                kTestEnvironment.awaitTimeout());
    }

    /**
     * Schedule a job that requires a cellular connection, and verify that it does not run when
     * the device is connected to a WiFi provider.
     */
    public void testCellularConstraintFails_withWiFi() throws Exception {
        if (!mHasWifi) {
            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
            return;
        }
        if (!checkDeviceSupportsMobileData()) {
            Log.d(TAG, "Skipping test that requires the device be mobile data enabled.");
            return;
        }
        setWifiMeteredState(false);

        kTestEnvironment.setExpectedExecutions(0);
        mJobScheduler.schedule(
                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_CELLULAR).build());
        runSatisfiedJob(CONNECTIVITY_JOB_ID);

        assertTrue("Job requiring cellular connectivity still executed on WiFi.",
                kTestEnvironment.awaitTimeout());
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when Data Saver is on and the device is not connected to WiFi.
     */
    public void testBgExpeditedJobDoesNotBypassDataSaver() throws Exception {
        if (hasEthernetConnection()) {
            Log.d(TAG, "Skipping test since ethernet is connected.");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered network.");
            return;
        }
        setDataSaverEnabled(true);

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_ANY, true);
        mTestAppInterface.runSatisfiedJob();

        assertFalse("BG expedited job requiring connectivity fired with Data Saver on.",
                mTestAppInterface.awaitJobStart(DEFAULT_TIMEOUT_MILLIS));
    }

    /**
     * Schedule an expedited job that requires a network connection, and verify that it runs even
     * when multiple firewalls are active.
     */
    public void testExpeditedJobDoesNotBypassSimultaneousFirewalls_withDataSaver()
            throws Exception {
        if (!BatteryUtils.isBatterySaverSupported()) {
            Log.d(TAG, "Skipping test that requires battery saver support");
            return;
        }
        if (mHasWifi) {
            setWifiMeteredState(true);
        } else if (checkDeviceSupportsMobileData()) {
            disconnectWifiToConnectToMobile();
        } else {
            Log.d(TAG, "Skipping test that requires a metered network.");
            return;
        }
        if (!AppStandbyUtils.isAppStandbyEnabled()) {
            Log.d(TAG, "App standby not enabled");
            return;
        }

        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.ENABLE_RESTRICTED_BUCKET, "1");
        mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
        SystemUtil.runShellCommand("am set-standby-bucket "
                + kJobServiceComponent.getPackageName() + " restricted");
        BatteryUtils.runDumpsysBatteryUnplug();
        BatteryUtils.enableBatterySaver(true);
        setDataSaverEnabled(true);

        mTestAppInterface = new TestAppInterface(mContext, CONNECTIVITY_JOB_ID);

        mTestAppInterface.scheduleJob(false,  JobInfo.NETWORK_TYPE_ANY, true);
        mTestAppInterface.runSatisfiedJob();

        assertFalse("Expedited job fired with multiple firewalls, including data saver.",
                mTestAppInterface.awaitJobStart(DEFAULT_TIMEOUT_MILLIS));
    }

    // --------------------------------------------------------------------------------------------
    // Utility methods
    // --------------------------------------------------------------------------------------------

    /**
     * Determine whether the device running these CTS tests should be subject to tests involving
     * mobile data.
     * @return True if this device will support a mobile data connection.
     */
    private boolean checkDeviceSupportsMobileData() {
        if (!mHasTelephony) {
            Log.d(TAG, "Skipping test that requires telephony features, not supported by this" +
                    " device");
            return false;
        }
        Network[] networks = mCm.getAllNetworks();
        for (Network network : networks) {
            if (mCm.getNetworkCapabilities(network)
                    .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                return true;
            }
        }
        Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
        return false;
    }

    private boolean hasEthernetConnection() {
        if (!mHasEthernet) return false;
        Network[] networks = mCm.getAllNetworks();
        for (Network network : networks) {
            if (mCm.getNetworkCapabilities(network).hasTransport(TRANSPORT_ETHERNET)) {
                return true;
            }
        }
        return false;
    }

    private String unquoteSSID(String ssid) {
        // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
        // Otherwise it's guaranteed not to start with a quote.
        if (ssid.charAt(0) == '"') {
            return ssid.substring(1, ssid.length() - 1);
        } else {
            return ssid;
        }
    }

    private String getWifiSSID() throws Exception {
        // Location needs to be enabled to get the WiFi information.
        setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
        final AtomicReference<String> ssid = new AtomicReference<>();
        SystemUtil.runWithShellPermissionIdentity(() -> {
            ssid.set(mWifiManager.getConnectionInfo().getSSID());
        }, Manifest.permission.ACCESS_FINE_LOCATION);
        return unquoteSSID(ssid.get());
    }

    private void setLocationMode(String mode) throws Exception {
        Settings.Secure.putString(mContext.getContentResolver(),
                Settings.Secure.LOCATION_MODE, mode);
        final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
        final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
        waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
                () -> wantEnabled == locationManager.isLocationEnabled());
    }

    // Returns "true", "false" or "none"
    private String getWifiMeteredStatus(String ssid) {
        // Interestingly giving the SSID as an argument to list wifi-networks
        // only works iff the network in question has the "false" policy.
        // Also unfortunately runShellCommand does not pass the command to the interpreter
        // so it's not possible to | grep the ssid.
        final String command = "cmd netpolicy list wifi-networks";
        final String policyString = SystemUtil.runShellCommand(command);

        final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
                Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
        if (!m.find()) {
            fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
                    + policyString);
        }
        return m.group(1);
    }

    private void setWifiMeteredState(boolean metered) throws Exception {
        if (metered) {
            // Make sure unmetered cellular networks don't interfere.
            setAirplaneMode(true);
            setWifiState(true, mCm, mWifiManager);
        }
        final String ssid = getWifiSSID();
        setWifiMeteredState(ssid, metered ? "true" : "false");
    }

    // metered should be "true", "false" or "none"
    private void setWifiMeteredState(String ssid, String metered) throws Exception {
        if (metered.equals(getWifiMeteredStatus(ssid))) {
            return;
        }
        SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
        assertEquals(getWifiMeteredStatus(ssid), metered);
    }

    /**
     * Ensure WiFi is enabled, and block until we've verified that we are in fact connected.
     */
    private void connectToWifi() throws Exception {
        setWifiState(true, mCm, mWifiManager);
    }

    /**
     * Ensure WiFi is disabled, and block until we've verified that we are in fact disconnected.
     */
    private void disconnectFromWifi() throws Exception {
        setWifiState(false, mCm, mWifiManager);
    }

    /** Ensures that the device has a wifi network saved. */
    static void ensureSavedWifiNetwork(WifiManager wifiManager) {
        final List<WifiConfiguration> savedNetworks =
                ShellIdentityUtils.invokeMethodWithShellPermissions(
                        wifiManager, WifiManager::getConfiguredNetworks);
        assertFalse("Need at least one saved wifi network", savedNetworks.isEmpty());
    }

    /**
     * Set Wifi connection to specific state, and block until we've verified
     * that we are in the state.
     * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
     */
    static void setWifiState(final boolean enable,
            final ConnectivityManager cm, final WifiManager wm) throws Exception {
        if (enable != isWiFiConnected(cm, wm)) {
            NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
            NetworkCapabilities nc = new NetworkCapabilities.Builder()
                    .addTransportType(TRANSPORT_WIFI)
                    .build();
            NetworkTracker tracker = new NetworkTracker(nc, enable, cm);
            cm.registerNetworkCallback(nr, tracker);

            if (enable) {
                SystemUtil.runShellCommand("svc wifi enable");
                waitUntil("Failed to enable Wifi", 30 /* seconds */, () -> wm.isWifiEnabled());
                //noinspection deprecation
                SystemUtil.runWithShellPermissionIdentity(wm::reconnect,
                        android.Manifest.permission.NETWORK_SETTINGS);
            } else {
                SystemUtil.runShellCommand("svc wifi disable");
            }

            tracker.waitForStateChange();

            assertTrue("Wifi must be " + (enable ? "connected to" : "disconnected from")
                            + " an access point for this test.",
                    enable == isWiFiConnected(cm, wm));

            cm.unregisterNetworkCallback(tracker);
        }
    }

    static boolean isWiFiConnected(final ConnectivityManager cm, final WifiManager wm) {
        if (!wm.isWifiEnabled()) {
            return false;
        }
        final Network network = cm.getActiveNetwork();
        if (network == null) {
            return false;
        }
        final NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(network);
        return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
    }

    /**
     * Disconnect from WiFi in an attempt to connect to cellular data. Worth noting that this is
     * best effort - there are no public APIs to force connecting to cell data. We disable WiFi
     * and wait for a broadcast that we're connected to cell.
     * We will not call into this function if the device doesn't support telephony.
     * @see #mHasTelephony
     * @see #checkDeviceSupportsMobileData()
     */
    private void disconnectWifiToConnectToMobile() throws Exception {
        setAirplaneMode(false);
        if (mHasWifi && mWifiManager.isWifiEnabled()) {
            NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
            NetworkCapabilities nc = new NetworkCapabilities.Builder()
                    .addTransportType(TRANSPORT_CELLULAR)
                    .build();
            NetworkTracker tracker = new NetworkTracker(nc, true, mCm);
            mCm.registerNetworkCallback(nr, tracker);

            disconnectFromWifi();

            assertTrue("Device must have access to a metered network for this test.",
                    tracker.waitForStateChange());

            mCm.unregisterNetworkCallback(tracker);
        }
    }

    /**
     * Ensures that restrict background data usage policy is turned off.
     * If the policy is on, it interferes with tests that relies on metered connection.
     */
    private void setDataSaverEnabled(boolean enabled) throws Exception {
        SystemUtil.runShellCommand(getInstrumentation(),
                enabled ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
    }

    private boolean isAirplaneModeOn() throws Exception {
        final String output = SystemUtil.runShellCommand(getInstrumentation(),
                "cmd connectivity airplane-mode").trim();
        return "enabled".equals(output);
    }

    private void setAirplaneMode(boolean on) throws Exception {
        if (isAirplaneModeOn() == on) {
            return;
        }
        final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
                new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
        SystemUtil.runShellCommand(getInstrumentation(),
                "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
        airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
                15 /* 15 seconds */);
        waitUntil("Networks didn't change to " + (!on ? " on" : " off"), 60 /* seconds */,
                () -> {
                    if (on) {
                        return mCm.getActiveNetwork() == null
                                && (!mHasWifi || !isWiFiConnected(mCm, mWifiManager));
                    } else {
                        return mCm.getActiveNetwork() != null;
                    }
                });
        // Wait some time for the network changes to propagate. Can't use
        // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
        // airplane mode status even though the network changes haven't propagated all the way to
        // JobScheduler.
        Thread.sleep(5000);
    }

    private static class NetworkTracker extends ConnectivityManager.NetworkCallback {
        private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
        private final ConnectivityManager mCm;

        private final CountDownLatch mReceiveLatch = new CountDownLatch(1);

        private final NetworkCapabilities mExpectedCapabilities;

        private final boolean mExpectedConnected;

        private final Handler mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
                    checkActiveNetwork();
                }
            }
        };

        private NetworkTracker(NetworkCapabilities expectedCapabilities, boolean expectedConnected,
                ConnectivityManager cm) {
            mExpectedCapabilities = expectedCapabilities;
            mExpectedConnected = expectedConnected;
            mCm = cm;
        }

        @Override
        public void onAvailable(Network network) {
            // Available doesn't mean it's the active network. We need to check that separately.
            checkActiveNetwork();
        }

        @Override
        public void onLost(Network network) {
            checkActiveNetwork();
        }

        boolean waitForStateChange() throws InterruptedException {
            checkActiveNetwork();
            return mReceiveLatch.await(60, TimeUnit.SECONDS);
        }

        private void checkActiveNetwork() {
            mHandler.removeMessages(MSG_CHECK_ACTIVE_NETWORK);
            if (mReceiveLatch.getCount() == 0) {
                return;
            }

            Network activeNetwork = mCm.getActiveNetwork();
            if (mExpectedConnected) {
                if (activeNetwork != null && mExpectedCapabilities.satisfiedByNetworkCapabilities(
                        mCm.getNetworkCapabilities(activeNetwork))) {
                    mReceiveLatch.countDown();
                } else {
                    mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
                }
            } else {
                if (activeNetwork == null
                        || !mExpectedCapabilities.satisfiedByNetworkCapabilities(
                        mCm.getNetworkCapabilities(activeNetwork))) {
                    mReceiveLatch.countDown();
                } else {
                    mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
                }
            }
        }
    }
}
