/*
 * Copyright (C) 2008 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;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.Client;
import com.android.ddmlib.ClientData;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.MultiLineReceiver;
import com.android.ddmlib.NullOutputReceiver;
import com.android.ddmlib.RawImage;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
import com.android.ddmlib.SyncService;
import com.android.ddmlib.SyncService.ISyncProgressMonitor;
import com.android.ddmlib.TimeoutException;
import com.android.ddmlib.log.LogReceiver;
import com.android.ddmlib.log.LogReceiver.ILogListener;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Manage the testing target device for<br>
 * <ul>
 *    <li> install/uninstall test package, and
 *    <li> execute command on device
 *    <li> get command feedback from standard output
 * </ul>
 */
public class TestDevice implements DeviceObserver {
    private static final String DEVICE_SETUP_APK = "TestDeviceSetup";
    private static final String DEVICE_SETUP_APP_PACKAGE_NAME = "android.tests.devicesetup";
    private static final String DEFAULT_TEST_RUNNER_NAME =
                                  "android.test.InstrumentationTestRunner";
    private static final String ACTION_INSTALL = "install";
    private static final String ACTION_UNINSTALL = "uninstall";
    private static final String ACTION_GET_DEV_INFO = "getDeviceInfo";
    private static final String sInstrumentResultExpr = "INSTRUMENTATION_RESULT: (\\S+)=(.+)";

    public static final int STATUS_IDLE = 0;
    public static final int STATUS_BUSY = STATUS_IDLE + 1;
    public static final int STATUS_OFFLINE = STATUS_IDLE + 2;
    private static final String STATUS_STR_IDLE = "idle";
    private static final String STATUS_STR_IN_USE = "in use";
    private static final String STATUS_STR_OFFLINE = "offline";

    /** Interval [ms] for polling a device until boot is completed. */
    private static final int REBOOT_POLL_INTERVAL = 5000;
    /** Number of times a booting device should be polled before we give up. */
    private static final int REBOOT_POLL_COUNT = 10 * 60 * 1000 / REBOOT_POLL_INTERVAL;
    /** Max time [ms] to wait for <code>adb shell getprop</code> to return a result. */
    private static final int GETPROP_TIMEOUT = 5000;

    public static final Pattern INSTRUMENT_RESULT_PATTERN;

    private BatchModeResultParser mBatchModeResultParser;

    private DeviceObserver mDeviceObserver;
    private IDevice mDevice;
    private DeviceParameterCollector mDeviceInfo;

    private SyncService mSyncService;

    private PackageActionObserver mUninstallObserver;

    private int mStatus;
    private static HashMap<Integer, String> mStatusMap;
    private PackageActionTimer mPackageActionTimer;

    private ObjectSync mObjectSync;

    private MultiplexingLogListener logListener = new MultiplexingLogListener();
    private LogReceiver logReceiver = new LogReceiver(logListener);

    private class LogServiceThread extends Thread {
        @Override
        public void run() {
            try {
                mDevice.runLogService("main", logReceiver);
            } catch (IOException e) {
            } catch (TimeoutException e) {
            } catch (AdbCommandRejectedException e) {
            }
        }

        /**
         * Cancel logging and exit this thread.
         */
        public void cancelLogService() {
            // this will cause the loop in our run method to
            // exit, terminating this thread.
            logReceiver.cancel();
        }
    }

    private LogServiceThread logServiceThread;

    static {
        INSTRUMENT_RESULT_PATTERN = Pattern.compile(sInstrumentResultExpr);
        mStatusMap = new HashMap<Integer, String>();
        mStatusMap.put(STATUS_IDLE, STATUS_STR_IDLE);
        mStatusMap.put(STATUS_BUSY, STATUS_STR_IN_USE);
        mStatusMap.put(STATUS_OFFLINE, STATUS_STR_OFFLINE);
    }

    // This constructor just for unit test
    TestDevice(final String serialNumber) {
        mDeviceInfo = new DeviceParameterCollector();
        mDeviceInfo.setSerialNumber(serialNumber);
    }

    public TestDevice(IDevice device) {
        mDevice = device;
        try {
            mSyncService = mDevice.getSyncService();
        } catch (IOException e) {
            // FIXME: handle failed connection.
        } catch (TimeoutException e) {
            // FIXME: handle failed connection.
        } catch (AdbCommandRejectedException e) {
            // FIXME: handle failed connection.
        }
        mBatchModeResultParser = null;
        mUninstallObserver = new PackageActionObserver(ACTION_UNINSTALL);
        mStatus = STATUS_IDLE;
        mDeviceInfo = new DeviceParameterCollector();
        mPackageActionTimer = new PackageActionTimer();
        mObjectSync = new ObjectSync();
    }

    /**
     * Gets this device's information.
     *
     * Assumes that the test device setup apk is already installed.
     * See {@link #installDeviceSetupApp()}.
     *
     * @return information of this device.
     */
    public DeviceParameterCollector getDeviceInfo()
                throws DeviceDisconnectedException, InvalidNameSpaceException,
                InvalidApkPathException {
        if (mDeviceInfo.size() == 0) {
            logServiceThread = new LogServiceThread();
            logServiceThread.start();
            genDeviceInfo();
        }
        return mDeviceInfo;
    }

    /**
     * Attempt to disable the screen guard on device.
     *
     * Assumes the test device setup apk is already installed.
     * See {@link #installDeviceSetupApp()}.
     *
     * Note: uninstalling the device setup app {@link #uninstallDeviceSetupApp()} will re-enable
     * keyguard.
     *
     * @throws DeviceDisconnectedException
     */
    public void disableKeyguard () throws DeviceDisconnectedException {
        final String commandStr = "am broadcast -a android.tests.util.disablekeyguard";
        Log.d(commandStr);

        executeShellCommand(commandStr, new NullOutputReceiver());
    }

    /**
     * Return the Device instance associated with this TestDevice.
     */
    public IDevice getDevice() {
        return mDevice;
    }

    class RestartPropReceiver extends MultiLineReceiver {
        private boolean mRestarted;
        private boolean mCancelled;
        private boolean mDone;

        @Override
        public void processNewLines(String[] lines) {
            for (String line : lines) {
                if (line.trim().equals("1")) {
                    mRestarted = true;
                }
            }
        }
        @Override
        public void done() {
            synchronized(this) {
                mDone = true;
                this.notifyAll();
            }
        }

        public boolean isCancelled() {
            return mCancelled;
        }

        boolean hasRestarted(long timeout) {
            try {
                synchronized (this) {
                    if (!mDone) {
                        this.wait(timeout);
                    }
                }
            } catch (InterruptedException e) {
                // ignore
            }
            mCancelled = true;
            return mRestarted;
        }
    }

    /**
     * Wait until device indicates that boot is complete.
     *
     * @return true if the device has completed the boot process, false if it does not, or the
     * device does not respond.
     */
    public boolean waitForBootComplete() throws DeviceDisconnectedException {
        Log.d("probe device status...");

        mDeviceInfo.set(DeviceParameterCollector.SERIAL_NUMBER, getSerialNumber());
        mObjectSync = new ObjectSync();

        // reset device observer
        DeviceObserver tmpDeviceObserver = mDeviceObserver;
        mDeviceObserver = this;

        int retries = 0;
        boolean success = false;
        while (!success && (retries < REBOOT_POLL_COUNT)) {
            Log.d("Waiting for device to complete boot");
            RestartPropReceiver rpr = new RestartPropReceiver();
            this.executeShellCommand("getprop dev.bootcomplete", rpr);
            success = rpr.hasRestarted(GETPROP_TIMEOUT);
            if (!success) {
                try {
                    Thread.sleep(REBOOT_POLL_INTERVAL);
                } catch (InterruptedException e) {
                    // ignore and retry
                }
                retries += 1;
            }
        }
        mDeviceObserver = tmpDeviceObserver;
        if (success) {
            Log.d("Device boot complete");
        }
        return success;
    }

    /**
     * Run device information collector command to got the device info.
     */
    private void genDeviceInfo() throws DeviceDisconnectedException,
                InvalidNameSpaceException, InvalidApkPathException {
        mDeviceInfo.set(DeviceParameterCollector.SERIAL_NUMBER, getSerialNumber());
        // run shell command to run device information collector
        Log.d("run device information collector");
        runDeviceInfoCollectorCommand();
        waitForCommandFinish();
    }

    /**
     * Uninstall the device setup apk from device.
     *
     * See {@link #installDeviceSetupApp}
     *
     * @throws DeviceDisconnectedException
     * @throws InvalidNameSpaceException
     */
    public void uninstallDeviceSetupApp() throws DeviceDisconnectedException,
            InvalidNameSpaceException {
        // reset device observer
        DeviceObserver tmpDeviceObserver = mDeviceObserver;
        mDeviceObserver = this;
        Log.d("uninstall get info ...");
        uninstallAPK(DEVICE_SETUP_APP_PACKAGE_NAME);
        waitForCommandFinish();
        Log.d("uninstall device information collector successfully");
        mDeviceObserver = tmpDeviceObserver;
    }

    /**
     * Install the device setup apk on the device.
     *
     * @throws DeviceDisconnectedException
     * @throws InvalidApkPathException
     */
    public void installDeviceSetupApp() throws DeviceDisconnectedException, InvalidApkPathException {
        String apkPath = HostConfig.getInstance().getCaseRepository().getApkPath(DEVICE_SETUP_APK);
        if (!HostUtils.isFileExist(apkPath)) {
            Log.e("File doesn't exist: " + apkPath, null);
            return;
        }

        Log.d("installing " + DEVICE_SETUP_APK + " apk");
        mObjectSync = new ObjectSync();

        // reset device observer
        DeviceObserver tmpDeviceObserver = mDeviceObserver;
        mDeviceObserver = this;

        Log.d("install get info ...");
        installAPK(apkPath);
        waitForCommandFinish();
        mDeviceObserver = tmpDeviceObserver;
    }

    /**
     * Run command to collect device info.
     */
    private void runDeviceInfoCollectorCommand() throws DeviceDisconnectedException {
        final String commandStr = "am instrument -w -e bundle true "
            + String.format("%s/android.tests.getinfo.DeviceInfoInstrument",
                    DEVICE_SETUP_APP_PACKAGE_NAME);
        Log.d(commandStr);

        mPackageActionTimer.start(ACTION_GET_DEV_INFO, this);
        executeShellCommand(commandStr, new DeviceInfoReceiver(mDeviceInfo));
    }

    /**
     * Receiver which receives and parses the device information.
     */
    final class DeviceInfoReceiver extends MultiLineReceiver {

        private ArrayList<String> mResultLines = new ArrayList<String>();
        private DeviceParameterCollector mDeviceParamCollector;

        public DeviceInfoReceiver(DeviceParameterCollector paramCollector) {
            super();
            mDeviceParamCollector = paramCollector;
            setTrimLine(false);
        }

        /** {@inheritDoc} */
        @Override
        public void processNewLines(String[] lines) {
            for (String line : lines) {
                mResultLines.add(line);
            }
        }

        /** {@inheritDoc} */
        public boolean isCancelled() {
            return false;
        }

        /** {@inheritDoc} */
        @Override
        public void done() {
            super.done();
            String key, value;
            for (String line : mResultLines) {
                Matcher matcher = INSTRUMENT_RESULT_PATTERN.matcher(line);
                if (matcher.matches()) {
                    key = matcher.group(1);
                    value = matcher.group(2);
                    mDeviceParamCollector.set(key, value);
                }
            }

            synchronized(mObjectSync) {
                mObjectSync.sendNotify();
            }
        }

    }

    /**
     * Store the build information of a device
     */
    public static final class DeviceParameterCollector{
        // the device info keys expected to be sent from device info instrumentation
        // these constants should match exactly with those defined in DeviceInfoInstrument.jaa
        public static final String PRODUCT_NAME = "buildName";
        public static final String BUILD_VERSION = "buildVersion";
        public static final String BUILD_ID = "buildID";
        public static final String BUILD_FINGERPRINT = "build_fingerprint";
        public static final String BUILD_TAGS = "build_tags";
        public static final String BUILD_TYPE = "build_type";
        public static final String BUILD_MANUFACTURER = "build_manufacturer";
        public static final String BUILD_MODEL = "build_model";
        public static final String BUILD_BRAND = "build_brand";
        public static final String BUILD_BOARD = "build_board";
        public static final String BUILD_DEVICE = "build_device";
        public static final String BUILD_ABI = "build_abi";
        public static final String BUILD_ABI2 = "build_abi2";
        public static final String SCREEN_SIZE = "screen_size";
        public static final String SCREEN_HEIGHT = "screen_height";
        public static final String SCREEN_WIDTH = "screen_width";
        public static final String SCREEN_DENSITY = "screen_density";
        public static final String SCREEN_DENSITY_BUCKET = "screen_density_bucket";
        public static final String SERIAL_NUMBER = "serialNumber";
        public static final String VERSION_SDK = "androidPlatformVersion";
        public static final String LOCALES = "locales";
        public static final String SCREEN_Y_DENSITY = "Ydpi";
        public static final String SCREEN_X_DENSITY = "Xdpi";
        public static final String TOUCH_SCREEN = "touch";
        public static final String NAVIGATION = "navigation";
        public static final String KEYPAD = "keypad";
        public static final String NETWORK = "network";
        public static final String IMEI = "imei";
        public static final String IMSI = "imsi";
        public static final String PHONE_NUMBER = "phoneNumber";
        public static final String FEATURES = "features";
        public static final String PROCESSES = "processes";
        public static final String OPEN_GL_ES_VERSION = "openGlEsVersion";

        private HashMap<String, String> mInfoMap;

        public DeviceParameterCollector() {
            mInfoMap = new HashMap<String, String>();
        }

        /**
         * Set the pair of key and value of device information.
         *
         * @param key The key of the pair.
         * @param value The value of the pair.
         */
        public void set(final String key, final String value) {
            mInfoMap.put(key, value);
        }

        /**
         * Return the number of device info items which stored in.
         *
         * @return the number of device info items which stored in.
         */
        public int size() {
            return mInfoMap.size();
        }

        /**
         * Set the build finger print.
         *
         * @param buildFingerPrint The build finger print.
         */
        public void setBuildFingerPrint(final String buildFingerPrint) {
            mInfoMap.put(BUILD_FINGERPRINT, buildFingerPrint);
        }

        /**
         * Set the build tags.
         *
         * @param buildTags The build tags.
         */
        public void setBuildTags(final String buildTags) {
            mInfoMap.put(BUILD_TAGS, buildTags);
        }

        /**
         * Set build type.
         *
         * @param buildType The build type.
         */
        public void setBuildType(final String buildType) {
            mInfoMap.put(BUILD_TYPE, buildType);
        }

        /**
         * Set the build model.
         *
         * @param buildModel The build model.
         */
        public void setBuildModel(final String buildModel) {
            mInfoMap.put(BUILD_MODEL, buildModel);
        }

        /**
         * Set the build brand.
         *
         * @param buildBrand The build brand.
         */
        public void setBuildBrand(final String buildBrand) {
            mInfoMap.put(BUILD_BRAND, buildBrand);
        }

        /**
         * Set the build board.
         *
         * @param buildBoard The build board.
         */
        public void setBuildBoard(final String buildBoard) {
            mInfoMap.put(BUILD_BOARD, buildBoard);
        }

        /**
         * Set the build device.
         *
         * @param buildDevice The build device.
         */
        public void setBuildDevice(final String buildDevice) {
            mInfoMap.put(BUILD_DEVICE, buildDevice);
        }

        /**
         * Set the build abi
         *
         * @param buildAbi The build ABI
         */
        public void setBuildAbi(final String buildAbi) {
            mInfoMap.put(BUILD_ABI, buildAbi);
        }

        /**
         * Set the build abi2
         *
         * @param buildAbi The build ABI2
         */
        public void setBuildAbi2(final String buildAbi2) {
            mInfoMap.put(BUILD_ABI2, buildAbi2);
        }

        /**
         * set the serialNumber of this device
         *
         * @param serialNumber The serial number.
         */
        public void setSerialNumber(final String serialNumber) {
            mInfoMap.put(SERIAL_NUMBER, serialNumber);
        }

        /**
         * set the build id
         *
         * @param bldId The build ID.
         */
        public void setBuildId(final String bldId) {
            mInfoMap.put(BUILD_ID, bldId);
        }

        /**
         * set the build version
         *
         * @param bldVer The build version.
         */
        public void setBuildVersion(final String bldVer) {
            mInfoMap.put(BUILD_VERSION, bldVer);
        }

        /**
         * set the product name
         **
         * @param productName The product name.
         */
        public void setProductName(final String productName) {
            mInfoMap.put(PRODUCT_NAME, productName);
        }

        /**
         * Get the build finger print.
         *
         * @return The build finger print.
         */
        public String getBuildFingerPrint() {
            return mInfoMap.get(BUILD_FINGERPRINT);
        }

        /**
         * Get the build tags.
         *
         * @return The build tags.
         */
        public String getBuildTags() {
            return mInfoMap.get(BUILD_TAGS);
        }

        /**
         * Get build type.
         *
         * @return The build type.
         */
        public String getBuildType() {
            return mInfoMap.get(BUILD_TYPE);
        }

        /**
         * Get the build model.
         *
         * @return The build model.
         */
        public String getBuildModel() {
            return mInfoMap.get(BUILD_MODEL);
        }

        /**
         * Get the build manufacturer.
         *
         * @return The build manufacturer.
         */
        public String getBuildManufacturer() {
            return mInfoMap.get(BUILD_MANUFACTURER);
        }

        /**
         * Get the build brand.
         *
         * @return The build brand.
         */
        public String getBuildBrand() {
            return mInfoMap.get(BUILD_BRAND);
        }

        /**
         * Get the build board.
         *
         * @return The build board.
         */
        public String getBuildBoard() {
            return mInfoMap.get(BUILD_BOARD);
        }

        /**
         * Get the build device.
         *
         * @return The build device.
         */
        public String getBuildDevice() {
            return mInfoMap.get(BUILD_DEVICE);
        }

        /**
         * Get the build ABI.
         *
         * @return The build ABI.
         */
        public String getBuildAbi() {
            return mInfoMap.get(BUILD_ABI);
        }

        /**
         * Get the build ABI2.
         *
         * @return The build ABI2.
         */
        public String getBuildAbi2() {
            return mInfoMap.get(BUILD_ABI2);
        }

        /**
         * get the build id
         **
         * @return The build ID.
         */
        public String getBuildId() {
            return mInfoMap.get(BUILD_ID);
        }

        /**
         * get the build version
         **
         * @return The build version.
         */
        public String getBuildVersion() {
            return mInfoMap.get(BUILD_VERSION);
        }

        /**
         * get the product name
         *
         * @return The product name.
         */
        public String getProductName() {
            return mInfoMap.get(PRODUCT_NAME);
        }

        /**
         * get the serial number
         *
         * @return The serial number.
         */
        public String getSerialNumber() {
            return mInfoMap.get(SERIAL_NUMBER);
        }

        public String getScreenSize() {
            return mInfoMap.get(SCREEN_SIZE);
        }

        /**
         * Return screen resolution(width x height)
         *
         * @return The screen resolution.
         */
        public String getScreenResolution() {
            return mInfoMap.get(SCREEN_WIDTH) + "x" + mInfoMap.get(SCREEN_HEIGHT);
        }

        /**
         * Return logical screen density
         *
         * @return The logical screen density.
         */
        public String getScreenDensity() {
            return mInfoMap.get(SCREEN_DENSITY);
        }

        /**
         * Return the probable screen density bucket
         *
         * @return The probable screen density bucket.
         */
        public String getScreenDensityBucket() {
            return mInfoMap.get(SCREEN_DENSITY_BUCKET);
        }

        /**
         * Get Android platform version.
         *
         * @return The Android platform version.
         */
        public String getAndroidPlatformVersion() {
            return mInfoMap.get(VERSION_SDK);
        }

        /**
         * Get supported locales.
         *
         * @return The supported locales.
         */
        public String getLocales() {
            return mInfoMap.get(LOCALES);
        }

        /**
         * Get x dip
         *
         * @return The X dip.
         */
        public String getXdpi() {
            return mInfoMap.get(SCREEN_X_DENSITY);
        }

        /**
         * Get y dip
         *
         * @return The y dip.
         */
        public String getYdpi() {
            return mInfoMap.get(SCREEN_Y_DENSITY);
        }

        /**
         * Get touch information
         *
         * @return The touch screen information.
         */
        public String getTouchInfo() {
            return mInfoMap.get(TOUCH_SCREEN);
        }

        /**
         * Get navigation information
         *
         * @return The navigation information.
         */
        public String getNavigation() {
            return mInfoMap.get(NAVIGATION);
        }

        /**
         * Get keypad information
         *
         * @return The keypad information.
         */
        public String getKeypad() {
            return mInfoMap.get(KEYPAD);
        }

        /**
         * Get network information
         *
         * @return The network information.
         */
        public String getNetwork() {
            return mInfoMap.get(NETWORK);
        }

        /**
         * Get IMEI
         *
         * @return IMEI.
         */
        public String getIMEI() {
            return mInfoMap.get(IMEI);
        }

        /**
         * Get IMSI
         *
         * @return IMSI.
         */
        public String getIMSI() {
            return mInfoMap.get(IMSI);
        }

        /**
         * Get phone number
         *
         * @return Phone number.
         */
        public String getPhoneNumber() {
            return mInfoMap.get(PHONE_NUMBER);
        }

        /**
         * Get features.
         *
         * @return Features.
         */
        public String getFeatures() {
            return mInfoMap.get(FEATURES);
        }

        /**
         * Get processes.
         *
         * @return Processes.
         */
        public String getProcesses() {
            return mInfoMap.get(PROCESSES);
        }

        /**
         * Get Open GL ES version.
         *
         * @return version or error message.
         */
        public String getOpenGlEsVersion() {
            return mInfoMap.get(OPEN_GL_ES_VERSION);
        }
    }

    /**
     * Get the serial number of the  {@link TestDevice}.
     *
     * @return the serial number of the {@link TestDevice}
     */
    public String getSerialNumber() {
        if (mDevice == null) {
            return mDeviceInfo.getSerialNumber();
        }
        return mDevice.getSerialNumber();
    }

    /**
     * Run a specified test.
     *
     * @param test The test to be run.
     */
    public void runTest(Test test) throws DeviceDisconnectedException {

        final String appNameSpace = test.getAppNameSpace();
        String runner = test.getInstrumentationRunner();
        if (runner == null) {
            runner = DEFAULT_TEST_RUNNER_NAME;
        }

        // need to doubly escape any '$' chars in the name since this string is
        // passed through two shells \\\$ -> \$ -> $
        final String testName = test.getFullName().replaceAll("\\$", "\\\\\\$");

        final String commandStr = "am instrument -w -r -e class " + testName
                + " " + appNameSpace + "/" + runner;
        Log.d(commandStr);
        executeShellCommand(commandStr, new IndividualModeResultParser(test));
    }

    /**
     * Run a test package in batch mode.
     *
     * @param testPackage The testPackage to be run.
     * @param javaPkgName The java package name. If null, run the whole test package;
     *              else, run the specified java package contained in the test package
     */
    public void runInBatchMode(TestPackage testPackage, final String javaPkgName)
                throws DeviceDisconnectedException {
        String appNameSpace = testPackage.getAppNameSpace();
        String runner = testPackage.getInstrumentationRunner();
        if (runner == null) {
            runner = DEFAULT_TEST_RUNNER_NAME;
        }

        String name = testPackage.getAppPackageName();
        if ((javaPkgName != null) && (javaPkgName.length() != 0)) {
            name = javaPkgName;
        }

        String cmdHeader = "am instrument -w -r -e package " + name + " ";
        final String commandStr = cmdHeader + appNameSpace + "/" + runner;
        Log.d(commandStr);

        mBatchModeResultParser = new BatchModeResultParser(testPackage);
        executeShellCommand(commandStr, mBatchModeResultParser);
    }

    /**
     * Run a in batch mode of a TestPackage.
     *
     * @param testPackage The testPackage to be run.
     * @param javaClassName The java class name.
     */
    public void runTestCaseInBatchMode(TestPackage testPackage, final String javaClassName,
            String profile) throws DeviceDisconnectedException {
        if (javaClassName == null) {
            return;
        }

        String appNameSpace = testPackage.getAppNameSpace();
        String runner = testPackage.getInstrumentationRunner();
        if (runner == null) {
            runner = DEFAULT_TEST_RUNNER_NAME;
        }

        String cmdHeader = "am instrument -w -r -e class " + javaClassName
                + " -e profile " + profile + " ";
        final String commandStr = cmdHeader + appNameSpace + "/" + runner;
        Log.d(commandStr);

        mBatchModeResultParser = new BatchModeResultParser(testPackage);
        executeShellCommand(commandStr, mBatchModeResultParser);
    }

    /**
     * Get clients.
     *
     * @return The clients.
     */
    public Client[] getClients() {
        return mDevice.getClients();
    }

    /**
     * Push a file to a given path.
     *
     * @param localPath The local path.
     * @param remotePath The remote path.
     */
    public void pushFile(String localPath, String remotePath) {
        try {
            mSyncService.pushFile(localPath, remotePath, new PushMonitor());
        } catch (TimeoutException e) {
            Log.e("Uploading file failed: timeout", null);
        } catch (SyncException e) {
            Log.e("Uploading file failed: " + e.getMessage(), null);
        } catch (FileNotFoundException e) {
            Log.e("Uploading file failed: " + e.getMessage(), null);
        } catch (IOException e) {
            Log.e("Uploading file failed: " + e.getMessage(), null);
        }
    }

    /**
     * Install a specified APK using adb command install.
     *
     * @param apkPath Name of the package to be installed.
     */
    public void installAPK(final String apkPath) throws DeviceDisconnectedException,
                InvalidApkPathException {
        if ((apkPath == null) || (apkPath.length() == 0) || (!HostUtils.isFileExist(apkPath))) {
            throw new InvalidApkPathException(apkPath);
        }

        // Use re-install directly
        final String cmd = DeviceManager.getAdbLocation() + " -s "
                + getSerialNumber() + " install -r " + apkPath;
        Log.d(cmd);

        mPackageActionTimer.start(ACTION_INSTALL, this);
        executeCommand(cmd, new PackageActionObserver(ACTION_INSTALL));
    }

    /**
     * Execute the given command.
     *
     * @param command The command to be executed.
     * @param stdOutReceiver The receiver for handling the output from the device.
     */
    private void executeCommand(String command, StdOutObserver stdOutReceiver)
                    throws DeviceDisconnectedException {
        if (mStatus != STATUS_OFFLINE) {
            try {
                Process proc = Runtime.getRuntime().exec(command);

                if (stdOutReceiver != null) {
                    stdOutReceiver.setInputStream(proc.getInputStream());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            throw new DeviceDisconnectedException(getSerialNumber());
        }
    }

    /**
     * Standard output observer.
     *
     */
    interface StdOutObserver {
        /**
         * set the input Stream.
         */
        public void setInputStream(InputStream is);

        /**
         * Process lines.
         */
        public void processLines() throws IOException;
    }

    /**
     * Un-install APK.
     *
     * @param packageName The package to be un-installed.
     */
    public void uninstallAPK(String packageName) throws DeviceDisconnectedException,
                InvalidNameSpaceException {
        if ((packageName == null) || (packageName.length() == 0)) {
            throw new InvalidNameSpaceException(packageName);
        }

        uninstallAPKImpl(packageName, mUninstallObserver);
    }

    /**
     * The implementation of uninstalling APK.
     *
     * @param packageName The package to be uninstalled.
     * @param observer The uninstall observer
     */
    private void uninstallAPKImpl(final String packageName, final PackageActionObserver observer)
                throws DeviceDisconnectedException {
        final String cmdStr = DeviceManager.getAdbLocation() + " -s "
                      + getSerialNumber() + " uninstall " + packageName;
        Log.d(cmdStr);
        mPackageActionTimer.start(ACTION_UNINSTALL, this);
        executeCommand(cmdStr, observer);
    }

    /**
     * Package action(install/uninstall) timeout task
     */
    class PackageActionTimeoutTask extends TimerTask {

        private String mAction;
        private TestDevice mTargetDevice;

        /**
         * Task of package action timeout.
         *
         * @param action string of action
         * @param testDevice the {@TestDevice} which got the timeout.
         */
        public PackageActionTimeoutTask(final String action,
                TestDevice testDevice) {
            mAction = action;
            mTargetDevice = testDevice;
        }

        /** {@inheritDoc}*/
        @Override
        public void run() {
            Log.d("PackageActionTimeoutTask.run(): mAction=" + mAction);
            synchronized (mObjectSync) {
                mObjectSync.sendNotify();
            }

            if (mAction.toLowerCase().equals(ACTION_INSTALL)) {
                mDeviceObserver.notifyInstallingTimeout(mTargetDevice);
            } else if (mAction.toLowerCase().equals(ACTION_UNINSTALL)) {
                mDeviceObserver.notifyUninstallingTimeout(mTargetDevice);
            } else if (mAction.toLowerCase().equals(ACTION_GET_DEV_INFO)) {
                Log.e("Get device information timeout", null);
            } else {
                Log.e("Timeout: " + mAction, null);
            }
        }
    }

    /**
     * Package action timer monitors the package action.
     *
     */
    class PackageActionTimer {
        private Timer mTimer;

        /**
         * Start the timer while package install/uninstall/getDeviceInfo/checkAPI.
         *
         * @param action The action of package.
         * @param device The TestDevice the action is taken over.
         */
        private void start(final String action, final TestDevice device) {
            start(action, HostConfig.Ints.packageInstallTimeoutMs.value(), device);
        }

        /**
         * Start the timer while package install/uninstall/getDeviceInfo/checkAPI with specific
         * timeout.
         *
         * @param action The action of package
         * @param timeout The specific timeout
         * @param device The TestDevice under operation
         */
        private void start(final String action, final int timeout, final TestDevice device) {
            Log.d("start(), action=" + action + ",mTimer=" + mTimer + ",timeout=" + timeout);
            synchronized (this) {
                if (mTimer != null) {
                    mTimer.cancel();
                }

                mTimer = new Timer();
                mTimer.schedule(new PackageActionTimeoutTask(action, device), timeout);
            }
        }

        /**
         * Stop the action timer.
         */
        private void stop() {
            synchronized (this) {
                Log.d("stop() , mTimer=" + mTimer);
                if (mTimer != null) {
                    mTimer.cancel();
                    mTimer = null;
                }
            }
        }
    }

    /**
     * The observer of package action, currently including installing and uninstalling.
     */
    final class PackageActionObserver implements StdOutObserver, Runnable {

        private BufferedReader mReader;
        private String mAction;

        public PackageActionObserver(final String action) {
            mAction = action;
        }

        /** {@inheritDoc} */
        public void run() {
            try {
                processLines();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    mReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * Parse the standard out to judge where the installation is complete.
         */
        public void processLines() throws IOException {
            String line = mReader.readLine();
            int statusCode = DeviceObserver.FAIL;
            boolean gotResult = false;

            while (line != null) {
                line = line.toLowerCase();
                if (line.indexOf("success") != -1) {
                    statusCode = DeviceObserver.SUCCESS;
                    gotResult = true;
                } else if (line.indexOf("failure") != -1) {
                    statusCode = DeviceObserver.FAIL;
                    CUIOutputStream.println(mAction.toLowerCase() + " met " + line);
                    gotResult = true;
                } else if (line.indexOf("error") != -1) {
                    CUIOutputStream.println(mAction.toLowerCase() + " met " + line);
                    statusCode = DeviceObserver.FAIL;
                    gotResult = true;
                }

                if (gotResult) {
                    Log.d(mAction + " calls stopPackageActionTimer()");
                    mPackageActionTimer.stop();

                    if (mDeviceObserver != null) {
                        mDeviceObserver.notifyInstallingComplete(statusCode);
                    }
                    break;
                }
                line = mReader.readLine();
            }
        }

        /** {@inheritDoc} */
        public void setInputStream(InputStream is) {
            mReader = new BufferedReader(new InputStreamReader(is));
            new Thread(this).start();
        }
    }

    /**
     * Raw mode result parser.
     */
    abstract class RawModeResultParser extends MultiLineReceiver {
        public final static String EQ_MARK = "=";
        public final static String COMMA_MARK = ":";
        public final static String AT_MARK = "at ";

        public final static String STATUS_STREAM = "INSTRUMENTATION_STATUS: stream=";
        public final static String STATUS_TEST = "INSTRUMENTATION_STATUS: test=";
        public final static String STATUS_CLASS = "INSTRUMENTATION_STATUS: class=";
        public final static String STATUS_CODE = "INSTRUMENTATION_STATUS_CODE:";
        public final static String STATUS_STACK = "INSTRUMENTATION_STATUS: stack=";
        public final static String STATUS_CURRENT = "INSTRUMENTATION_STATUS: current=";
        public final static String STATUS_NUM = "INSTRUMENTATION_STATUS: numtests=";
        public final static String STATUS_ERROR_STR = "INSTRUMENTATION_STATUS: Error=";

        public final static String FAILURE = "Failure in ";
        public final static String ASSERTION = "junit.framework.Assertion";

        public final static String RESULT_STREAM = "INSTRUMENTATION_RESULT: stream=";
        public final static String RESULT_CODE = "INSTRUMENTATION_CODE:";
        public final static String RESULT = "Test results";
        public final static String RESULT_TIME = "Time:";
        public final static String RESULT_SUMMARY = "Tests run:";

        public final static int STATUS_STARTING = 1;
        public final static int STATUS_PASS = 0;
        public final static int STATUS_FAIL = -1;
        public final static int STATUS_ERROR = -2;
        public final static int STATUS_OMITTED = -3;

        private ArrayList<String> mResultLines;

        public String mStackTrace;
        public String mFailedMsg;
        public int mResultCode;

        public Test mTest;

        public RawModeResultParser(Test test) {
            super();

            setTrimLine(false);

            mTest = test;
            mResultLines = new ArrayList<String>();
            mStackTrace = null;
            mFailedMsg = null;
            mResultCode = CtsTestResult.CODE_FAIL;
        }

        /** {@inheritDoc} */
        @Override
        public void processNewLines(String[] lines) {
            for (String line : lines) {
                processNewLine(line.trim());
            }
        }

        /**
         * Process the new line.
         *
         * @param line The new line.
         */
        abstract public void processNewLine(final String line);

        /**
         * Get the result lines.
         *
         * @return The result lines.
         */
        public ArrayList<String> getResultLines() {
            return mResultLines;
        }

        /**
         * Get the named string from the string containing the mark.
         *
         * @param mark The mark to search against the results.
         * @return The test name.
         */
        public String getNamedString(String mark) {
            for (String line : mResultLines) {
                if (line.startsWith(mark)) {
                    String name = line.substring(line.indexOf(EQ_MARK) + 1);
                    return name.trim();
                }
            }

            return null;
        }

        /**
         * Parse the int from the string containing the mark.
         *
         * @param mark The mark to search against the results.
         * @return The number.
         */
        public int parseIntWithMark(String mark) {
            for (String line : mResultLines) {
                if (line.startsWith(mark)) {
                    String code = line.substring(line.indexOf(EQ_MARK) + 1);
                    return Integer.parseInt(code.trim());
                }
            }

            return 0;
        }

        /**
         * Get failed message.
         *
         * @return The failed message.
         */
        public String getFailedMessage() {
            Iterator<String> iterator = mResultLines.iterator();
            while (iterator.hasNext()) {
                String line = iterator.next();
                if (line.startsWith(STATUS_STACK)) {
                    String failedMsg = line.substring(STATUS_STACK.length());
                    if (iterator.hasNext()) {
                        failedMsg += " " + iterator.next();
                    }
                    return failedMsg;
                }
            }
            return null;
        }

        /**
         * Get stack trace from output result.
         *
         * @return The stack trace message.
         */
        public String getStackTrace() {
            StringBuilder sb = new StringBuilder();
            for (String line : mResultLines) {
                line = line.trim();
                if (line.startsWith(AT_MARK) && line.endsWith(")")) {
                    sb.append(line + "\n");
                }
            }
            return sb.toString();
        }

        /**
         * Get the status code of the test result.
         *
         * @param line The string contains the status code of the test result.
         * @return The status code of the test result.
         */
        public int getStatusCode(String line) {
            String codeStr = line.substring(line.indexOf(COMMA_MARK) + 1);
            return Integer.parseInt(codeStr.trim());
        }

        /** {@inheritDoc} */
        public boolean isCancelled() {
            return false;
        }

        /** {@inheritDoc} */
        @Override
        public void done() {
            super.done();
        }
    }

    /**
     * Individual mode result parser. <br>
     * Individual mode means that the host sends request
     * to the device method by method. And the device
     * reactions and outputs the result to each request.
     */
    final class IndividualModeResultParser extends RawModeResultParser {

        public IndividualModeResultParser(Test test) {
            super(test);
        }

        /**
         * Process a new line.
         *
         * @param line The new line.
         */
        @Override
        public void processNewLine(final String line) {
            if ((line == null) || (line.trim().length() == 0)) {
                return;
            }

            ArrayList<String> resultLines = getResultLines();
            resultLines.add(line);

            if (line.startsWith(STATUS_CODE)) {
                int statusCode = getStatusCode(line);
                processTestResult(statusCode);
                resultLines.removeAll(resultLines);
            }
        }

        /**
         * Process the test result of a single test.
         *
         * @param statusCode The status code of a single test's test result.
         */
        public void processTestResult(int statusCode) {
            String testName = getNamedString(STATUS_TEST);
            String className = getNamedString(STATUS_CLASS);
            String testFullName = className + Test.METHOD_SEPARATOR + testName;
            String errorMessage = getNamedString(STATUS_ERROR_STR);

            mFailedMsg = null;
            mStackTrace = null;
            if ((statusCode == STATUS_FAIL) || (statusCode == STATUS_ERROR)) {
                mFailedMsg = getFailedMessage();
                mStackTrace = getStackTrace();
            }

            if ((errorMessage != null) && (errorMessage.length() != 0)) {
                if (mFailedMsg == null) {
                    mFailedMsg = errorMessage;
                } else {
                    mFailedMsg += " : " + errorMessage;
                }
            }

            Log.d(testFullName + "...(" + statusCode + ")");
            Log.d("errorMessage= " + errorMessage);
            Log.d("mFailedMsg=" + mFailedMsg);
            Log.d("mStackTrace=" + mStackTrace);

            switch (statusCode) {
            case STATUS_STARTING:
                break;

            case STATUS_PASS:
                mResultCode = CtsTestResult.CODE_PASS;
                break;

            case STATUS_FAIL:
            case STATUS_ERROR:
                mResultCode = CtsTestResult.CODE_FAIL;
                break;

            case STATUS_OMITTED:
                mResultCode = CtsTestResult.CODE_OMITTED;
                break;
            }
        }

        /** {@inheritDoc} */
        @Override
        public void done() {
            mTest.notifyResult(new CtsTestResult(mResultCode, mFailedMsg, mStackTrace));
            super.done();
        }
    }

    /**
     * Batch mode result parser.
     * Batch mode means that the host sends only one request
     * for all of the methods contained in the package to the
     * device. And then, the device runs the method one by one
     * and outputs the result method by method.
     */
    final class BatchModeResultParser extends RawModeResultParser {
        private TestPackage mTestPackage;
        private Collection<Test> mTests;
        public int mCurrentTestNum;
        public int mTotalNum;

        public BatchModeResultParser(TestPackage testPackage) {
            super(null);

            mTestPackage = testPackage;
            if (mTestPackage != null) {
                mTests = mTestPackage.getTests();
            }
        }

        /**
         * Process a new line.
         *
         * @param line The new line.
         */
        @Override
        public void processNewLine(final String line) {
            if ((line == null) || (line.trim().length() == 0)) {
                return;
            }

            ArrayList<String> resultLines = getResultLines();
            resultLines.add(line);

            if (line.startsWith(STATUS_CODE)) {
                int statusCode = getStatusCode(line);
                processTestResult(statusCode);
                resultLines.removeAll(resultLines);
            } else if (line.startsWith(RESULT_CODE)) {
                int resultCode = getStatusCode(line);
                switch(resultCode) {
                case STATUS_STARTING:
                    break;

                case STATUS_FAIL:
                case STATUS_ERROR:
                    mResultCode = CtsTestResult.CODE_FAIL;
                    break;

                case STATUS_PASS:
                    mResultCode = CtsTestResult.CODE_PASS;
                    break;

                case STATUS_OMITTED:
                    mResultCode = CtsTestResult.CODE_OMITTED;
                    break;
                }
                resultLines.removeAll(resultLines);
            }
        }

        /**
         * Process the test result of a single test.
         *
         * @param statusCode The status code of a single test's test result.
         */
        public void processTestResult(int statusCode) {
            String testName = getNamedString(STATUS_TEST);
            String className = getNamedString(STATUS_CLASS);
            String testFullName = className + Test.METHOD_SEPARATOR + testName;
            mCurrentTestNum = parseIntWithMark(STATUS_CURRENT);
            mTotalNum = parseIntWithMark(STATUS_NUM);

            mFailedMsg = null;
            mStackTrace = null;
            if ((statusCode == STATUS_FAIL) || ((statusCode == STATUS_ERROR))) {
                mFailedMsg = getFailedMessage();
                mStackTrace = getStackTrace();
            }

            Log.d(testFullName + "...(" + statusCode + ")");
            Log.d("mFailedMsg=" + mFailedMsg);
            Log.d("mStackTrace=" + mStackTrace);

            String status = TestPackage.FINISH;

            if (statusCode == STATUS_STARTING) {
                status = TestPackage.START;
            }

            mTest = searchTest(testFullName);
            if (mTest != null) {
                switch(statusCode) {
                case STATUS_STARTING:
                    status = TestPackage.START;
                    break;

                case STATUS_PASS:
                    mTest.setResult(new CtsTestResult(
                            CtsTestResult.CODE_PASS, null, null));
                    break;

                case STATUS_ERROR:
                case STATUS_FAIL:
                    mTest.setResult(new CtsTestResult(
                            CtsTestResult.CODE_FAIL, mFailedMsg, mStackTrace));
                    break;

                case STATUS_OMITTED:
                    mTest.setResult(new CtsTestResult(CtsTestResult.CODE_OMITTED));
                    break;
                }
            }
            // report status even if no matching test was found
            mTestPackage.notifyTestStatus(mTest, status);
        }

        /**
         * Search Test with given test full name.
         *
         * @param testFullName The test full name.
         * @return The Test matches the test full name given.
         */
        private Test searchTest(String testFullName) {
            for (Test test : mTests) {
                if (testFullName.equals(test.getFullName())) {
                    return test;
                }
            }
            return null;
        }

        /** {@inheritDoc} */
        @Override
        public void done() {
            mTestPackage.notifyBatchModeFinish();
            super.done();
        }
    }

    /**
     * Remove the run time listener.
     */
    public void removeRuntimeListener() {
        mDeviceObserver = null;
    }

    /**
     * Set the run time listener.
     *
     * @param listener The run time listener.
     */
    public void setRuntimeListener(DeviceObserver listener) {
        mDeviceObserver = listener;
    }

    /**
     * Push monitor monitoring the status of pushing a file.
     */
    class PushMonitor implements ISyncProgressMonitor {

        public PushMonitor() {
        }

        /** {@inheritDoc} */
        public void advance(int arg0) {
        }

        /** {@inheritDoc} */
        public boolean isCanceled() {
            return false;
        }

        /** {@inheritDoc} */
        public void start(int arg0) {
        }

        /** {@inheritDoc} */
        public void startSubTask(String arg0) {
        }

        /** {@inheritDoc} */
        public void stop() {
        }
    }

    /**
     * Add a new log listener.
     *
     * @param listener the listener
     */
    public void addMainLogListener(ILogListener listener) {
        logListener.addListener(listener);
    }

    /**
     * Remove an existing log listener.
     *
     * @param listener the listener to remove.
     */
    public void removeMainLogListener(ILogListener listener) {
        logListener.removeListener(listener);
    }

    /**
     * Execute Adb shell command on {@link IDevice}
     *
     * @param cmd the string of command.
     * @param receiver {@link IShellOutputReceiver}
     * @throws DeviceDisconnectedException if the device disconnects during the command
     */
    public void executeShellCommand(final String cmd,
            final IShellOutputReceiver receiver) throws DeviceDisconnectedException {
        executeShellCommand(cmd, receiver, null);
    }

    /**
     * Execute Adb shell command on {@link IDevice}
     *
     * Note that the receivers run in a different thread than the caller.
     *
     * @param cmd the string of command.
     * @param receiver {@link IShellOutputReceiver}
     * @param logReceiver {@link LogReceiver}
     * @throws DeviceDisconnectedException if the device disconnects during the command
     */
    public void executeShellCommand(final String cmd,
            final IShellOutputReceiver receiver,
            final LogReceiver logReceiver)
            throws DeviceDisconnectedException {
        if (mStatus == STATUS_OFFLINE) {
            Log.d(String.format("device %s is offline when attempting to execute %s",
                    getSerialNumber(), cmd));
            throw new DeviceDisconnectedException(getSerialNumber());
        }

        new Thread() {
            @Override
            public void run() {
                try {
                    mDevice.executeShellCommand(cmd, receiver, 0);
                } catch (IOException e) {
                    Log.e(String.format("Failed to execute shell command %s on device %s", cmd,
                            mDevice.getSerialNumber()), e);
                } catch (TimeoutException e) {
                    Log.e(String.format("Failed to execute shell command %s on device %s", cmd,
                            mDevice.getSerialNumber()), e);
                } catch (AdbCommandRejectedException e) {
                    Log.e(String.format("Failed to execute shell command %s on device %s", cmd,
                            mDevice.getSerialNumber()), e);
                } catch (ShellCommandUnresponsiveException e) {
                    Log.e(String.format("Failed to execute shell command %s on device %s", cmd,
                            mDevice.getSerialNumber()), e);
                }
            }
        }.start();
    }

    /**
     * Kill {@link Client} which running the test on the {@link IDevice}
     *
     * @param packageName the test package name
     */
    public void killProcess(String packageName) {
        if (mStatus == STATUS_OFFLINE) {
            return;
        }
        Client[] clients = mDevice.getClients();

        for (Client c : clients) {
            ClientData cd = c.getClientData();
            if (cd.getClientDescription() == null) {
                continue;
            }
            if (cd.getClientDescription().equals(packageName)) {
                c.kill();
                break;
            }
        }
    }

    /**
     * Called when the {@link TestDevice} disconnected.
     */
    public void disconnected() {
        CUIOutputStream.println("Device(" + getSerialNumber() + ") disconnected");
        mDevice = null;
        mSyncService = null;

        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
            mPackageActionTimer.stop();
        }

        if (mStatus == STATUS_BUSY) {
            Log.d("TestDevice.disconnected calls notifyTestingDeviceDisconnected");
            mDeviceObserver.notifyTestingDeviceDisconnected();
        } else {
            if (!TestSession.isADBServerRestartedMode()) {
                CUIOutputStream.printPrompt();
            }
        }
        setStatus(STATUS_OFFLINE);
        if (logServiceThread != null) {
            logServiceThread.cancelLogService();
        }
    }

    /**
     * Set the status of the {@link TestDevice}
     *
     * @param statusCode the status code of {@link TestDevice}
     */
    public void setStatus(final int statusCode) {
        if (statusCode != STATUS_IDLE && statusCode != STATUS_BUSY
                && statusCode != STATUS_OFFLINE) {
            throw new IllegalArgumentException("Invalid status code");
        }
        mStatus = statusCode;
    }

    /**
     * Get the status code of the {@link TestDevice}.
     *
     * @return get the status code of the {@link TestDevice}
     */
    public int getStatus() {
        return mStatus;
    }

    /**
     * Get the status of the {@link TestDevice} as string.
     *
     * @return the status of the {@link TestDevice} as string.
     */
    public String getStatusAsString() {
        return mStatusMap.get(mStatus);
    }

    /**
     * Wait for command finish.
     */
    public void waitForCommandFinish() {
        synchronized (mObjectSync) {
            try {
                mObjectSync.waitOn();
            } catch (InterruptedException e) {
            }
        }
    }

    /**
     * Start the action timer with specific timeout
     *
     * @param action the action to start the timer
     * @param timeout the specific timeout
     */
    void startActionTimer(final String action, final int timeout) {
        mPackageActionTimer.start(action, timeout, this);
    }

    /**
     * Start the action timer.
     *
     * @param action the action to start the timer.
     */
    void startActionTimer(String action) {
       mPackageActionTimer.start(action, this);
    }

    /**
     * Stop the action timer.
     */
    void stopActionTimer() {
        mPackageActionTimer.stop();
    }

    /**
     * Allows an external test to signal that it's command is complete.
     */
    void notifyExternalTestComplete() {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
        }
    }

    /**
     * Notify install complete.
     */
    public void notifyInstallingComplete(int resultCode) {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
            mPackageActionTimer.stop();
        }
    }

    /** {@inheritDoc} */
    public void notifyInstallingTimeout(TestDevice testDevice) {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
        }
    }

    /** {@inheritDoc} */
    public void notifyTestingDeviceDisconnected() {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
            if (mPackageActionTimer != null) {
                mPackageActionTimer.stop();
            }
        }
    }

    /** {@inheritDoc} */
    public void notifyUninstallingComplete(int resultCode) {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
            mPackageActionTimer.stop();
        }
    }

    /** {@inheritDoc} */
    public void notifyUninstallingTimeout(TestDevice testDevice) {
        synchronized (mObjectSync) {
            mObjectSync.sendNotify();
        }
    }

    /**
     * Synchronization object for communication between threads.
     */
    class ObjectSync {
        private boolean mNotifySent = false;

        /**
         * Send notify to the waiting thread.
         */
        public void sendNotify() {
            Log.d("ObjectSync.sendNotify() is called, mNotifySent=" + mNotifySent);
            mNotifySent = true;
            notify();
        }

        /**
         * Wait on.
         */
        public void waitOn() throws InterruptedException {
            Log.d("ObjectSync.waitOn() is called, mNotifySent=" + mNotifySent);
            if (!mNotifySent) {
                wait();
            }

            mNotifySent = false;
        }

        /**
         * Check if notify has been sent to the waiting thread.
         *
         * @return If sent, return true; else, return false.
         */
        public boolean isNotified() {
            return mNotifySent;
        }
    }

    /**
     * Take a screenshot of the device under test.
     *
     * @return the screenshot
     * @throws IOException
     * @throws AdbCommandRejectedException
     * @throws TimeoutException
     */
    public RawImage getScreenshot() throws IOException, TimeoutException,
            AdbCommandRejectedException {
        return mDevice.getScreenshot();
    }
}
