/*
 * Copyright (C) 2010 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 com.android.cts.tradefed.testtype;

import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.device.DeviceInfoCollector;
import com.android.cts.tradefed.result.CtsTestStatus;
import com.android.cts.tradefed.result.PlanCreator;
import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.TestDeviceOptions;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.ResultForwarder;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.ITargetCleaner;
import com.android.tradefed.targetprep.ITargetPreparer;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IResumableTest;
import com.android.tradefed.testtype.IShardableTest;
import com.android.tradefed.testtype.InstrumentationTest;
import com.android.tradefed.util.AbiFormatter;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;

import junit.framework.Test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;


/**
 * A {@link Test} for running CTS tests.
 * <p/>
 * Supports running all the tests contained in a CTS plan, or individual test packages.
 */
public class CtsTest implements IDeviceTest, IResumableTest, IShardableTest, IBuildReceiver {
    private static final String LOG_TAG = "CtsTest";

    public static final String PLAN_OPTION = "plan";
    private static final String PACKAGE_OPTION = "package";
    private static final String CLASS_OPTION = "class";
    private static final String METHOD_OPTION = "method";
    private static final String TEST_OPTION = "test";
    public static final String CONTINUE_OPTION = "continue-session";
    public static final String RUN_KNOWN_FAILURES_OPTION = "run-known-failures";
    private static final String INCLUDE_FILTERS_OPTION = "include";
    private static final String EXCLUDE_FILTERS_OPTION = "exclude";

    public static final String PACKAGE_NAME_METRIC = "packageName";
    public static final String PACKAGE_ABI_METRIC = "packageAbi";
    public static final String PACKAGE_DIGEST_METRIC = "packageDigest";

    @Option(name = PLAN_OPTION, description = "the test plan to run.",
            importance = Importance.IF_UNSET)
    private String mPlanName = null;

    @Option(name = PACKAGE_OPTION, shortName = 'p', description = "the test packages(s) to run.",
            importance = Importance.IF_UNSET)
    private Collection<String> mPackageNames = new ArrayList<String>();

    @Option(name = "exclude-package", description = "the test packages(s) to exclude from the run.")
    private Collection<String> mExcludedPackageNames = new ArrayList<String>();

    @Option(name = CLASS_OPTION, shortName = 'c', description = "run a specific test class.",
            importance = Importance.IF_UNSET)
    private String mClassName = null;

    @Option(name = METHOD_OPTION, shortName = 'm',
            description = "run a specific test method, from given --class.",
            importance = Importance.IF_UNSET)
    private String mMethodName = null;

    @Option(name = TEST_OPTION, shortName = 't', description = "run a specific test",
            importance = Importance.IF_UNSET)
    private String mTestName = null;

    @Option(name = CONTINUE_OPTION,
            description = "continue a previous test session.",
            importance = Importance.IF_UNSET)
    private Integer mContinueSessionId = null;

    @Option(name = "skip-device-info", shortName = 'd', description =
        "flag to control whether to collect info from device. Providing this flag will speed up " +
        "test execution for short test runs but will result in required data being omitted from " +
        "the test report.")
    private boolean mSkipDeviceInfo = false;

    @Option(name = "resume", description =
        "flag to attempt to automatically resume aborted test run on another connected device. ")
    private boolean mResume = false;

    @Option(name = "shards", description =
        "shard the tests to run into separately runnable chunks to execute on multiple devices " +
        "concurrently.")
    private int mShards = 1;

    @Option(name = "screenshot", description =
        "flag for taking a screenshot of the device when test execution is complete.")
    private boolean mScreenshot = false;

    @Option(name = "bugreport", shortName = 'b', description =
        "take a bugreport after each failed test. " +
        "Warning: can potentially use a lot of disk space.")
    private boolean mBugreport = false;

    @Option(name = RUN_KNOWN_FAILURES_OPTION, shortName = 'k', description =
        "run tests including known failures")
    private boolean mIncludeKnownFailures;

    @Option(name = "disable-reboot", description =
            "Do not reboot device after running some amount of tests. Default behavior is to reboot.")
    private boolean mDisableReboot = false;

    @Option(name = "reboot-wait-time", description =
            "Additional wait time in ms after boot complete.")
    private int mRebootWaitTimeMSec = 2 * 60 * 1000;

    @Option(name = "reboot-interval", description =
            "Interval between each reboot in min.")
    private int mRebootIntervalMin = 30;

    @Option(name = "screenshot-on-failure", description =
            "take a screenshot on every test failure.")
    private boolean mScreenshotOnFailures = false;

    @Option(name = "logcat-on-failure", description =
            "take a logcat snapshot on every test failure. Unlike --bugreport, this can capture" +
            "logs even if connection with device has been lost, as well as being much more " +
            "performant.")
    private boolean mLogcatOnFailures = false;

    @Option(name = AbiFormatter.FORCE_ABI_STRING,
            description = AbiFormatter.FORCE_ABI_DESCRIPTION,
            importance = Importance.IF_UNSET)
    private String mForceAbi = null;

    @Option(name = "logcat-on-failure-size", description =
            "The max number of logcat data in bytes to capture when --logcat-on-failure is on. " +
            "Should be an amount that can comfortably fit in memory.")
    private int mMaxLogcatBytes = 500 * 1024; // 500K

    @Option(name = "collect-deqp-logs", description =
            "Collect dEQP logs from the device.")
    private boolean mCollectDeqpLogs = false;

    @Option(name = INCLUDE_FILTERS_OPTION, description = "Positive filters to pass to tests.")
    private List<String> mPositiveFilters = new ArrayList<> ();

    @Option(name = EXCLUDE_FILTERS_OPTION, description = "Negative filters to pass to tests.")
    private List<String> mNegativeFilters = new ArrayList<> ();

    @Option(name = "min-pre-reboot-package-count", description =
            "The minimum number of packages to require a pre test reboot")
    private int mMinPreRebootPackageCount = 2;
    private final int mShardAssignment;
    private final int mTotalShards;
    private ITestDevice mDevice = null;
    private CtsBuildHelper mCtsBuild = null;
    private IBuildInfo mBuildInfo = null;
    // last reboot time
    private long mPrevRebootTime;
    // The list of packages to run. populated in {@code setupTestPackageList}
    // This is a member variable so that run can be called more than once
    // and the test run is resumed.
    private List<TestPackage> mTestPackageList = new ArrayList<>();
    // The index in the pacakge list of the last test to complete
    private int mLastTestPackageIndex = 0;

    /** data structure for a {@link IRemoteTest} and its known tests */
    static class TestPackage {
        private final IRemoteTest mTestForPackage;
        private final ITestPackageDef mPackageDef;
        private final Collection<TestIdentifier> mKnownTests;

        TestPackage(ITestPackageDef packageDef, IRemoteTest testForPackage) {
            mPackageDef = packageDef;
            mTestForPackage = testForPackage;
            mKnownTests = packageDef.getTests();
        }

        IRemoteTest getTestForPackage() {
            return mTestForPackage;
        }

        Collection<TestIdentifier> getKnownTests() {
            return mKnownTests;
        }

        ITestPackageDef getPackageDef() {
            return mPackageDef;
        }

        /**
         * @return the test run name that should be used for the TestPackage.
         */
        String getTestRunName() {
            return mPackageDef.getId();
        }

        /**
         * @return the ABI on which the test will run.
         */
        IAbi getAbi() {
            return mPackageDef.getAbi();
        }
    }

    /**
     * A {@link ResultForwarder} that will forward a bugreport on each failed test.
     */
    private static class FailedTestBugreportGenerator extends ResultForwarder {
        private ITestDevice mDevice;

        public FailedTestBugreportGenerator(ITestInvocationListener listener, ITestDevice device) {
            super(listener);
            mDevice = device;
        }

        @Override
        public void testFailed(TestIdentifier test, String trace) {
            super.testFailed(test, trace);
            InputStreamSource bugSource = mDevice.getBugreport();
            super.testLog(String.format("bug-%s_%s", test.getClassName(), test.getTestName()),
                    LogDataType.TEXT, bugSource);
            bugSource.cancel();
        }
    }

    /**
     * A {@link ResultForwarder} that will forward a logcat snapshot on each failed test.
     */
    private static class FailedTestLogcatGenerator extends ResultForwarder {
        private ITestDevice mDevice;
        private int mNumLogcatBytes;

        public FailedTestLogcatGenerator(ITestInvocationListener listener, ITestDevice device,
                int maxLogcatBytes) {
            super(listener);
            mDevice = device;
            mNumLogcatBytes = maxLogcatBytes;
        }

        @Override
        public void testFailed(TestIdentifier test, String trace) {
            super.testFailed(test, trace);
            // sleep 2s to ensure test failure stack trace makes it into logcat capture
            RunUtil.getDefault().sleep(2 * 1000);
            InputStreamSource logSource = mDevice.getLogcat(mNumLogcatBytes);
            super.testLog(String.format("logcat-%s_%s", test.getClassName(), test.getTestName()),
                    LogDataType.TEXT, logSource);
            logSource.cancel();
        }
    }

    /**
     * A {@link ResultForwarder} that will forward a screenshot on test failures.
     */
    private static class FailedTestScreenshotGenerator extends ResultForwarder {
        private ITestDevice mDevice;

        public FailedTestScreenshotGenerator(ITestInvocationListener listener,
                ITestDevice device) {
            super(listener);
            mDevice = device;
        }

        @Override
        public void testFailed(TestIdentifier test, String trace) {
            super.testFailed(test, trace);

            try {
                InputStreamSource screenSource = mDevice.getScreenshot();
                super.testLog(String.format("screenshot-%s_%s", test.getClassName(),
                        test.getTestName()), LogDataType.PNG, screenSource);
                screenSource.cancel();
            } catch (DeviceNotAvailableException e) {
                // TODO: rethrow this somehow
                CLog.e("Device %s became unavailable while capturing screenshot, %s",
                        mDevice.getSerialNumber(), e.toString());
            }
        }
    }

    /**
     * Create a new {@link CtsTest} that will run the default list of {@link TestPackage}s.
     */
    public CtsTest() {
        this(0 /*shardAssignment*/, 1 /*totalShards*/);
    }

    /**
     * Create a new {@link CtsTest} that will run the given {@link List} of {@link TestPackage}s.
     */
    public CtsTest(int shardAssignment, int totalShards) {
        if (shardAssignment < 0) {
            throw new IllegalArgumentException(
                "shardAssignment cannot be negative. found:" + shardAssignment);
        }
        if (totalShards < 1) {
            throw new IllegalArgumentException(
                "shardAssignment must be at least 1. found:" + totalShards);
        }
        this.mShardAssignment = shardAssignment;
        this.mTotalShards = totalShards;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice getDevice() {
        return mDevice;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDevice(ITestDevice device) {
        mDevice = device;
    }

    /**
     * Set the plan name to run.
     * <p/>
     * Exposed for unit testing
     */
    void setPlanName(String planName) {
        mPlanName = planName;
    }

    /**
     * Set the skip collect device info flag.
     * <p/>
     * Exposed for unit testing
     */
    void setSkipDeviceInfo(boolean skipDeviceInfo) {
        mSkipDeviceInfo = skipDeviceInfo;
    }

    /**
     * Adds a package name to the list of test packages to run.
     * <p/>
     * Exposed for unit testing
     */
    void addPackageName(String packageName) {
        mPackageNames.add(packageName);
    }

    /**
     * Adds a package name to the list of test packages to exclude.
     * <p/>
     * Exposed for unit testing
     */
    void addExcludedPackageName(String packageName) {
        mExcludedPackageNames.add(packageName);
    }

    /**
     * Set the test class name to run.
     * <p/>
     * Exposed for unit testing
     */
    void setClassName(String className) {
        mClassName = className;
    }

    /**
     * Set the test method name to run.
     * <p/>
     * Exposed for unit testing
     */
    void setMethodName(String methodName) {
        mMethodName = methodName;
    }

    /**
     * Set the test name to run e.g. android.test.cts.SampleTest#testSample
     * <p/>
     * Exposed for unit testing
     */
    void setTestName(String testName) {
        mTestName = testName;
    }

    /**
     * Sets the test session id to continue.
     * <p/>
     * Exposed for unit testing
     */
     void setContinueSessionId(int sessionId) {
        mContinueSessionId = sessionId;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isResumable() {
        return mResume;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setBuild(IBuildInfo build) {
        mCtsBuild = CtsBuildHelper.createBuildHelper(build);
        mBuildInfo = build;
    }

    /**
     * Set the CTS build container.
     * <p/>
     * Exposed so unit tests can mock the provided build.
     */
    void setBuildHelper(CtsBuildHelper buildHelper) {
        mCtsBuild = buildHelper;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
        if (getDevice() == null) {
            throw new IllegalArgumentException("missing device");
        }

        Set<String> abiSet = getAbis();
        if (abiSet == null || abiSet.isEmpty()) {
            throw new IllegalArgumentException("could not get device's ABIs");
        }
        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "ABIs: " + abiSet);

        checkFields();
        setupTestPackageList(abiSet);
        if (mBugreport) {
            listener = new FailedTestBugreportGenerator(listener, getDevice());
        }
        if (mScreenshotOnFailures) {
            listener = new FailedTestScreenshotGenerator(listener, getDevice());
        }
        if (mLogcatOnFailures) {
            listener = new FailedTestLogcatGenerator(listener, getDevice(), mMaxLogcatBytes);
        }

        // Setup the a map of Test id to ResultFilter
        Map<String, ResultFilter> filterMap = new HashMap<>();
        int totalTestCount = 0;
        for (TestPackage testPackage : mTestPackageList) {
            ResultFilter resultFilter = new ResultFilter(listener, testPackage);
            totalTestCount += resultFilter.getKnownTestCount();
            filterMap.put(testPackage.getPackageDef().getId(), resultFilter);
        }

        // collect and install the prerequisiteApks first, to save time when multiple test
        // packages are using the same prerequisite apk
        Map<String, Set<String>> prerequisiteApks = getPrerequisiteApks(mTestPackageList, abiSet);
        Collection<String> uninstallPackages = getPrerequisitePackageNames(mTestPackageList);

        try {
            // always collect the device info, even for resumed runs, since test will likely be
            // running on a different device
            collectDeviceInfo(getDevice(), mCtsBuild, listener);
            preRebootIfNecessary(mTestPackageList);

            mPrevRebootTime = System.currentTimeMillis();
            int remainingPackageCount = mTestPackageList.size();
            Log.logAndDisplay(LogLevel.INFO, LOG_TAG,
                String.format("Start test run of %,d packages, containing %,d tests",
                    remainingPackageCount, totalTestCount));
            IAbi currentAbi = null;

            for (int i = mLastTestPackageIndex; i < mTestPackageList.size(); i++) {
                TestPackage testPackage = mTestPackageList.get(i);

                if (currentAbi == null ||
                    !currentAbi.getName().equals(testPackage.getAbi().getName())) {
                    currentAbi = testPackage.getAbi();
                    installPrerequisiteApks(
                        prerequisiteApks.get(currentAbi.getName()), currentAbi);
                }

                IRemoteTest test = testPackage.getTestForPackage();
                if (test instanceof IBuildReceiver) {
                    ((IBuildReceiver) test).setBuild(mBuildInfo);
                }
                if (test instanceof IDeviceTest) {
                    ((IDeviceTest) test).setDevice(getDevice());
                }
                if (test instanceof DeqpTestRunner) {
                    ((DeqpTestRunner)test).setCollectLogs(mCollectDeqpLogs);
                }
                if (test instanceof GeeTest) {
                    if (!mPositiveFilters.isEmpty()) {
                        String positivePatterns = join(mPositiveFilters, ":");
                        ((GeeTest)test).setPositiveFilters(positivePatterns);
                    }
                    if (!mNegativeFilters.isEmpty()) {
                        String negativePatterns = join(mNegativeFilters, ":");
                        ((GeeTest)test).setPositiveFilters(negativePatterns);
                    }
                }
                if (test instanceof InstrumentationTest) {
                    if (!mPositiveFilters.isEmpty()) {
                        String annotation = join(mPositiveFilters, ",");
                        ((InstrumentationTest)test).addInstrumentationArg(
                                "annotation", annotation);
                    }
                    if (!mNegativeFilters.isEmpty()) {
                        String notAnnotation = join(mNegativeFilters, ",");
                        ((InstrumentationTest)test).addInstrumentationArg(
                                "notAnnotation", notAnnotation);
                    }
                }

                forwardPackageDetails(testPackage.getPackageDef(), listener);
                performPackagePrepareSetup(testPackage.getPackageDef());
                test.run(filterMap.get(testPackage.getPackageDef().getId()));
                performPackagePreparerTearDown(testPackage.getPackageDef());
                if (i < mTestPackageList.size() - 1) {
                    TestPackage nextPackage = mTestPackageList.get(i + 1);
                    rebootIfNecessary(testPackage, nextPackage);
                    changeToHomeScreen();
                }
                // Track of the last complete test package index for resume
                mLastTestPackageIndex = i;
            }

            if (mScreenshot) {
                InputStreamSource screenshotSource = getDevice().getScreenshot();
                try {
                    listener.testLog("screenshot", LogDataType.PNG, screenshotSource);
                } finally {
                    screenshotSource.cancel();
                }
            }

            uninstallPrequisiteApks(uninstallPackages);

        } catch (RuntimeException e) {
            CLog.e(e);
            throw e;
        } catch (Error e) {
            CLog.e(e);
            throw e;
        } finally {
            for (ResultFilter filter : filterMap.values()) {
                filter.reportUnexecutedTests();
            }
        }
    }

    /**
     * Invokes {@link ITargetPreparer}s configured for the test package. {@link TargetSetupError}s
     * thrown by any preparer will be rethrown as {@link RuntimeException} so that the entire test
     * package will be skipped for execution. Note that preparers will be invoked in the same order
     * as they are defined in the module test config.
     * @param packageDef definition for the test package
     * @throws DeviceNotAvailableException
     */
    private void performPackagePrepareSetup(ITestPackageDef packageDef)
            throws DeviceNotAvailableException {
        List<ITargetPreparer> preparers = packageDef.getPackagePreparers();
        if (preparers != null) {
            for (ITargetPreparer preparer : preparers) {
                if (preparer instanceof IAbiReceiver) {
                    ((IAbiReceiver) preparer).setAbi(packageDef.getAbi());
                }
                try {
                    preparer.setUp(getDevice(), mBuildInfo);
                } catch (BuildError e) {
                    // This should only happen for flashing new build
                    CLog.e("Unexpected BuildError from preparer: %s",
                        preparer.getClass().getCanonicalName());
                } catch (TargetSetupError e) {
                    // log preparer class then rethrow & let caller handle
                    CLog.e("TargetSetupError in preparer: %s",
                        preparer.getClass().getCanonicalName());
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * Invokes clean up step for {@link ITargetCleaner}s configured for the test package. Note that
     * the cleaners will be invoked in the reverse order as they are defined in module test config.
     * @param packageDef definition for the test package
     * @throws DeviceNotAvailableException
     */
    private void performPackagePreparerTearDown(ITestPackageDef packageDef)
            throws DeviceNotAvailableException {
        List<ITargetPreparer> preparers = packageDef.getPackagePreparers();
        if (preparers != null) {
            ListIterator<ITargetPreparer> itr = preparers.listIterator(preparers.size());
            // do teardown in reverse order
            while (itr.hasPrevious()) {
                ITargetPreparer preparer = itr.previous();
                if (preparer instanceof ITargetCleaner) {
                    ((ITargetCleaner) preparer).tearDown(getDevice(), mBuildInfo, null);
                }
            }
        }
    }

    /**
     * Helper method to join strings. Exposed for unit tests
     * @param input
     * @param conjunction
     * @return string with elements of the input list with interleaved conjunction.
     */
    protected static String join(List<String> input, String conjunction) {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String item : input) {
            if (first) {
                first = false;
            } else {
                sb.append(conjunction);
            }
            sb.append(item);
        }
        return sb.toString();
    }

    /**
     * @param allTestPackageDefList The package list to filter
     * @param deviceAbiSet The ABIs supported by the device being tested
     * @return A {@link List} of {@link ITestPackageDef}s that should be tested
     */
    private static List<ITestPackageDef> filterByAbi(
            List<ITestPackageDef> allTestPackageDefList, Set<String> deviceAbiSet) {
        List<ITestPackageDef> filteredTestPackageDefList = new LinkedList<>();
        for (ITestPackageDef testPackageDef : allTestPackageDefList) {
            if (deviceAbiSet.contains(testPackageDef.getAbi().getName())) {
                // We only need test packages that are not empty and of matching ABIs
                filteredTestPackageDefList.add(testPackageDef);
            }
        }
        return filteredTestPackageDefList;
    }

    /** Reboot then the device iff the list of packages exceeds the minimum */
    private void preRebootIfNecessary(List<TestPackage> testPackageList)
            throws DeviceNotAvailableException {
        if (mDisableReboot) {
            return;
        }

        Set<String> packageNameSet = new HashSet<>();
        for (TestPackage testPackage : testPackageList) {
            // Parse the package name
            packageNameSet.add(AbiUtils.parseTestName(testPackage.getPackageDef().getId()));
        }
        if (packageNameSet.size() < mMinPreRebootPackageCount) {
            // There is actually only one unique package name. No need to reboot.
            return;
        }

        // Reboot is needed
        Log.logAndDisplay(LogLevel.INFO, LOG_TAG,
            String.format("Pre-test reboot (%,d packages). Use --disable-reboot to skip",
                packageNameSet.size()));

        rebootDevice();
    }

    private void rebootIfNecessary(TestPackage testFinished, TestPackage testToRun)
            throws DeviceNotAvailableException {
        // If there comes spurious failure like INJECT_EVENTS for a package,
        // reboot it before running it.
        // Also reboot after package which is know to leave pop-up behind
        final List<String> rebootAfterList = Arrays.asList(
                "CtsMediaTestCases",
                "CtsAccessibilityTestCases");
        final List<String> rebootBeforeList = Arrays.asList(
                "CtsAnimationTestCases",
                "CtsGraphicsTestCases",
                "CtsViewTestCases",
                "CtsWidgetTestCases" );
        long intervalInMSec = mRebootIntervalMin * 60 * 1000;
        if (mDisableReboot || mDevice.getSerialNumber().startsWith("emulator-")) {
            return;
        }
        long currentTime = System.currentTimeMillis();
        if (((currentTime - mPrevRebootTime) > intervalInMSec) ||
                rebootAfterList.contains(testFinished.getPackageDef().getName()) ||
                rebootBeforeList.contains(testToRun.getPackageDef().getName()) ) {
            Log.i(LOG_TAG,
                    String.format("Rebooting after running package %s, before package %s",
                            testFinished.getPackageDef().getName(),
                            testToRun.getPackageDef().getName()));
            rebootDevice();
            mPrevRebootTime = System.currentTimeMillis();
        }
    }

    private void rebootDevice() throws DeviceNotAvailableException {
        final int TIMEOUT_MS = 10 * 60 * 1000;
        TestDeviceOptions options = mDevice.getOptions();
        // store default value and increase time-out for reboot
        int rebootTimeout = options.getRebootTimeout();
        long onlineTimeout = options.getOnlineTimeout();
        options.setRebootTimeout(TIMEOUT_MS);
        options.setOnlineTimeout(TIMEOUT_MS);
        mDevice.setOptions(options);

        mDevice.reboot();

        // restore default values
        options.setRebootTimeout(rebootTimeout);
        options.setOnlineTimeout(onlineTimeout);
        mDevice.setOptions(options);
        Log.i(LOG_TAG, "Rebooting done");
        try {
            Thread.sleep(mRebootWaitTimeMSec);
        } catch (InterruptedException e) {
            Log.i(LOG_TAG, "Boot wait interrupted");
        }
    }

    /**
     * Remove artifacts like status bar from the previous test.
     * But this cannot dismiss dialog popped-up.
     */
    private void changeToHomeScreen() throws DeviceNotAvailableException {
        final String homeCmd = "input keyevent 3";

        mDevice.executeShellCommand(homeCmd);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            //ignore
        }
    }

    /**
     * Set {@code mTestPackageList} to the list of test packages to run filtered by ABI.
     */
    private void setupTestPackageList(Set<String> abis) throws DeviceNotAvailableException {
        if (!mTestPackageList.isEmpty()) {
            Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Resume tests using existing package list");
            return;
        }
        try {
            // Collect ALL tests
            ITestPackageRepo testRepo = createTestCaseRepo();
            List<ITestPackageDef> testPkgDefs = new ArrayList<>(getAvailableTestPackages(testRepo));
            testPkgDefs = filterByAbi(testPkgDefs, abis);
            // Note: run() relies on the fact that the list is reliably sorted for sharding purposes
            Collections.sort(testPkgDefs);
            // Create test package list.
            List<TestPackage> testPackageList = new ArrayList<>();
            for (ITestPackageDef testPackageDef : testPkgDefs) {
                // Note: createTest filters the test list inside of testPackageDef by exclusion list
                IRemoteTest testForPackage = testPackageDef.createTest(mCtsBuild.getTestCasesDir());
                if (testPackageDef.getTests().size() > 0) {
                    testPackageList.add(new TestPackage(testPackageDef, testForPackage));
                }
            }

            // Filter by shard
            int numTestPackages = testPackageList.size();
            int totalShards = Math.min(mTotalShards, numTestPackages);

            List<TestPackage> shardTestPackageList = new ArrayList<>();
            for (int i = mShardAssignment; i < numTestPackages; i += totalShards) {
                shardTestPackageList.add(testPackageList.get(i));
            }
            mTestPackageList.addAll(shardTestPackageList);
        } catch (FileNotFoundException e) {
            throw new IllegalArgumentException("failed to find test plan file", e);
        } catch (ParseException e) {
            throw new IllegalArgumentException("failed to parse test plan file", e);
        } catch (ConfigurationException e) {
            throw new IllegalArgumentException("failed to process arguments", e);
        }
    }

    /**
     * Return the {@link Set} of {@link ITestPackageDef}s to run unfiltered by ABI
     *
     * @return the {@link Set} of {@link ITestPackageDef}s to run
     * @throws ParseException
     * @throws FileNotFoundException
     * @throws ConfigurationException
     */
    private Set<ITestPackageDef> getAvailableTestPackages(ITestPackageRepo testRepo)
                throws ParseException, FileNotFoundException, ConfigurationException {
        // use LinkedHashSet to have predictable iteration order
        Set<ITestPackageDef> testPkgDefs = new LinkedHashSet<>();
        if (mPlanName != null) {
            Log.i(LOG_TAG, String.format("Executing CTS test plan %s", mPlanName));
            File ctsPlanFile = mCtsBuild.getTestPlanFile(mPlanName);
            ITestPlan plan = createPlan(mPlanName);
            plan.parse(createXmlStream(ctsPlanFile));

            for (String testId : plan.getTestIds()) {
                if (mExcludedPackageNames.contains(AbiUtils.parseTestName(testId))) {
                    continue;
                }
                ITestPackageDef testPackageDef = testRepo.getTestPackage(testId);
                if (testPackageDef == null) {
                    CLog.e("Could not find test id %s referenced in plan %s", testId, mPlanName);
                    continue;
                }

                testPackageDef.setTestFilter(plan.getTestFilter(testId));
                testPkgDefs.add(testPackageDef);
            }
        } else if (mPackageNames.size() > 0){
            Log.i(LOG_TAG, String.format("Executing test packages %s", mPackageNames));

            Map<String, List<ITestPackageDef>> testPackageDefMap =
                    testRepo.getTestPackageDefsByName();

            for (String name : mPackageNames) {
                if (!testPackageDefMap.containsKey(name)) {
                    throw new IllegalArgumentException(String.format(
                            "Could not find test package %s. " +
                                    "Use 'list packages' to see available packages.", name));
                }
                testPkgDefs.addAll(testPackageDefMap.get(name));
            }
        } else if (mClassName != null) {
            Log.i(LOG_TAG, String.format("Executing CTS test class %s", mClassName));
            testPkgDefs.addAll(buildTestPackageDefSet(testRepo, mClassName, mMethodName));
        } else if (mTestName != null) {
            Log.i(LOG_TAG, String.format("Executing CTS test %s", mTestName));
            String [] split = mTestName.split("#");
            if (split.length != 2) {
                Log.logAndDisplay(LogLevel.WARN, LOG_TAG, String.format(
                        "Could not parse class and method from test %s", mTestName));
            } else {
                String className = split[0];
                String methodName = split[1];
                testPkgDefs.addAll(buildTestPackageDefSet(testRepo, className, methodName));
            }
        } else if (mContinueSessionId != null) {
            // create an in-memory derived plan that contains the notExecuted tests from previous
            // session use timestamp as plan name so it will hopefully be unique
            String uniquePlanName = Long.toString(System.currentTimeMillis());
            PlanCreator planCreator = new PlanCreator(uniquePlanName, mContinueSessionId,
                    CtsTestStatus.NOT_EXECUTED);
            ITestPlan plan = createPlan(planCreator);
            for (String testId : plan.getTestIds()) {
                if (mExcludedPackageNames.contains(AbiUtils.parseTestName(testId))) {
                    continue;
                }
                ITestPackageDef testPackageDef = testRepo.getTestPackage(testId);
                if (testPackageDef == null) {
                    CLog.e("Could not find test id %s referenced in plan %s", testId, mPlanName);
                    continue;
                }

                testPackageDef.setTestFilter(plan.getTestFilter(testId));
                testPkgDefs.add(testPackageDef);
            }
        } else {
            // should never get here - was checkFields() not called?
            throw new IllegalStateException("nothing to run?");
        }
        return testPkgDefs;
    }

    /**
     * Return the list of unique prerequisite Android package names
     *
     * @param testPackages The {@link TestPackage}s that contain prerequisites
     */
    private Collection<String> getPrerequisitePackageNames(List<TestPackage> testPackages) {
        Set<String> pkgNames = new HashSet<>();
        for (TestPackage testPkg : testPackages) {
            String pkgName = testPkg.mPackageDef.getTargetPackageName();
            if (pkgName != null) {
                pkgNames.add(pkgName);
            }
        }
        return pkgNames;
    }

    /**
     * @return a {@link Set} containing {@link ITestPackageDef}s pertaining to the given
     *     {@code className} and {@code methodName}.
     */
    private static Set<ITestPackageDef> buildTestPackageDefSet(
            ITestPackageRepo testRepo, String className, String methodName) {
        Set<ITestPackageDef> testPkgDefs = new LinkedHashSet<>();
        // try to find packages to run from class name
        List<String> packageIds = testRepo.findPackageIdsForTest(className);
        if (packageIds.isEmpty()) {
            Log.logAndDisplay(LogLevel.WARN, LOG_TAG, String.format(
                    "Could not find package for test class %s", className));
        }
        for (String packageId: packageIds) {
            ITestPackageDef testPackageDef = testRepo.getTestPackage(packageId);
            if (testPackageDef != null) {
                testPackageDef.setClassName(className, methodName);
                testPkgDefs.add(testPackageDef);
            }
        }
        return testPkgDefs;
    }

    /**
     * Return the list (by abi) of unique prerequisite apks to install
     *
     * @param testPackages The {@link List} of {@link TestPackage} that contain prerequisite APKs
     */
    private Map<String, Set<String>> getPrerequisiteApks(
            List<TestPackage> testPackages, Set<String> abiSet) {
        Map<String, Set<String>> abiToApkMap = new HashMap<>();
        for (TestPackage testPkg : testPackages) {
            if (testPkg.getKnownTests().size() == 0) {
                // No tests, no point in installing pre-reqs
                continue;
            }
            String apkName = testPkg.mPackageDef.getTargetApkName();
            if (apkName == null) {
                continue;
            }
            String abiName = testPkg.getAbi().getName();
            if (!abiSet.contains(abiName)) {
                continue;
            }

            if (!abiToApkMap.containsKey(abiName)) {
                abiToApkMap.put(abiName, new HashSet<String>());
            }
            abiToApkMap.get(abiName).add(apkName);
        }
        return abiToApkMap;
    }

    /**
     * FIXME eventually this should be removed once we get rid of CtsTestStubs, any other
     * prerequisite apks should be installed by the test runner
     *
     * Install the collection of test apk file names
     *
     * @param prerequisiteApks The APKs that must be installed
     * @throws DeviceNotAvailableException
     */
    private void installPrerequisiteApks(Collection<String> prerequisiteApks, IAbi abi)
            throws DeviceNotAvailableException {
        if (prerequisiteApks == null) {
            return;
        }
        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Installing prerequisites");
        for (String apkName : prerequisiteApks) {
            try {
                File apkFile = mCtsBuild.getTestApp(apkName);
                String[] options = {AbiUtils.createAbiFlag(abi.getName())};
                String errorCode = getDevice().installPackage(apkFile, true, options);
                if (errorCode != null) {
                    CLog.e("Failed to install %s. Reason: %s", apkName, errorCode);
                }
            } catch (FileNotFoundException e) {
                CLog.e("Could not find test apk %s", apkName);
            }
        }
    }

    /**
     * Uninstalls the collection of android package names from device.
     *
     * @param uninstallPackages The packages that must be uninstalled
     */
    private void uninstallPrequisiteApks(Collection<String> uninstallPackages)
            throws DeviceNotAvailableException {
        for (String pkgName : uninstallPackages) {
            getDevice().uninstallPackage(pkgName);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Collection<IRemoteTest> split() {
        if (mShards <= 1) {
            return null;
        }
        checkFields();

        List<IRemoteTest> shardQueue = new LinkedList<>();
        for (int shardAssignment = 0; shardAssignment < mShards; shardAssignment++) {
            CtsTest ctsTest = new CtsTest(shardAssignment, mShards /* totalShards */);
            OptionCopier.copyOptionsNoThrow(this, ctsTest);
            // Set the shard count because the copy option on the previous line copies
            // over the mShard value
            ctsTest.mShards = 0;
            shardQueue.add(ctsTest);
        }

        return shardQueue;
    }

    /**
     * Runs the device info collector instrumentation on device, and forwards it to test listeners
     * as run metrics.
     * <p/>
     * Exposed so unit tests can mock.
     *
     * @throws DeviceNotAvailableException
     */
    void collectDeviceInfo(ITestDevice device, CtsBuildHelper ctsBuild,
            ITestInvocationListener listener) throws DeviceNotAvailableException {
        if (!mSkipDeviceInfo) {
            String abi = AbiFormatter.getDefaultAbi(device, "");
            DeviceInfoCollector.collectDeviceInfo(device, abi, ctsBuild.getTestCasesDir(), listener);
            DeviceInfoCollector.collectExtendedDeviceInfo(
                device, abi, ctsBuild.getTestCasesDir(), listener, mBuildInfo);
        }
    }

    /**
     * Factory method for creating a {@link ITestPackageRepo}.
     * <p/>
     * Exposed for unit testing
     */
    ITestPackageRepo createTestCaseRepo() {
        return new TestPackageRepo(mCtsBuild.getTestCasesDir(), mIncludeKnownFailures);
    }

    /**
     * Factory method for creating a {@link TestPlan}.
     * <p/>
     * Exposed for unit testing
     */
    ITestPlan createPlan(String planName) {
        return new TestPlan(planName, AbiUtils.getAbisSupportedByCts());
    }

    /**
     * Gets the set of ABIs supported by both CTS and the device under test
     * <p/>
     * Exposed for unit testing
     * @return The set of ABIs to run the tests on
     * @throws DeviceNotAvailableException
     */
    Set<String> getAbis() throws DeviceNotAvailableException {
        String bitness = (mForceAbi == null) ? "" : mForceAbi;
        Set<String> abis = new HashSet<>();
        for (String abi : AbiFormatter.getSupportedAbis(mDevice, bitness)) {
            if (AbiUtils.isAbiSupportedByCts(abi)) {
                abis.add(abi);
            }
        }
        return abis;
    }

    /**
     * Factory method for creating a {@link TestPlan} from a {@link PlanCreator}.
     * <p/>
     * Exposed for unit testing
     * @throws ConfigurationException
     */
    ITestPlan createPlan(PlanCreator planCreator)
            throws ConfigurationException {
        return planCreator.createDerivedPlan(mCtsBuild, AbiUtils.getAbisSupportedByCts());
    }

    /**
     * Factory method for creating a {@link InputStream} from a plan xml file.
     * <p/>
     * Exposed for unit testing
     */
    InputStream createXmlStream(File xmlFile) throws FileNotFoundException {
        return new BufferedInputStream(new FileInputStream(xmlFile));
    }

    private void checkFields() {
        // for simplicity of command line usage, make --plan, --package, --test and --class mutually
        // exclusive
        boolean mutualExclusiveArgs = xor(mPlanName != null, mPackageNames.size() > 0,
                mClassName != null, mContinueSessionId != null, mTestName != null);

        if (!mutualExclusiveArgs) {
            throw new IllegalArgumentException(String.format(
                    "Ambiguous or missing arguments. " +
                    "One and only one of --%s --%s(s), --%s or --%s to run can be specified",
                    PLAN_OPTION, PACKAGE_OPTION, CLASS_OPTION, CONTINUE_OPTION));
        }
        if (mMethodName != null && mClassName == null) {
            throw new IllegalArgumentException(String.format(
                    "Must specify --%s when --%s is used", CLASS_OPTION, METHOD_OPTION));
        }
        if (mCtsBuild == null) {
            throw new IllegalArgumentException("missing CTS build");
        }
    }

    /**
     * Helper method to perform exclusive or on list of boolean arguments
     *
     * @param args set of booleans on which to perform exclusive or
     * @return <code>true</code> if one and only one of <var>args</code> is <code>true</code>.
     *         Otherwise return <code>false</code>.
     */
    private static boolean xor(boolean... args) {
        boolean currentVal = args[0];
        for (int i=1; i < args.length; i++) {
            if (currentVal && args[i]) {
                return false;
            }
            currentVal |= args[i];
        }
        return currentVal;
    }

    /**
     * Forward the digest and package name to the listener as a metric
     *
     * @param listener Handles test results
     */
    private static void forwardPackageDetails(ITestPackageDef def, ITestInvocationListener listener) {
        Map<String, String> metrics = new HashMap<>(3);
        metrics.put(PACKAGE_NAME_METRIC, def.getName());
        metrics.put(PACKAGE_ABI_METRIC, def.getAbi().getName());
        metrics.put(PACKAGE_DIGEST_METRIC, def.getDigest());
        listener.testRunStarted(def.getId(), 0);
        listener.testRunEnded(0, metrics);
    }
}
