/*
 * 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.tradefed.device;

import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
import com.android.ddmlib.DdmPreferences;
import com.android.ddmlib.EmulatorConsole;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IDevice.DeviceState;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.command.remote.DeviceDescriptor;
import com.android.tradefed.config.GlobalConfiguration;
import com.android.tradefed.config.IGlobalConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.IDeviceMonitor.DeviceLister;
import com.android.tradefed.device.IManagedTestDevice.DeviceEventResponse;
import com.android.tradefed.device.cloud.VmRemoteDevice;
import com.android.tradefed.host.IHostOptions;
import com.android.tradefed.log.ILogRegistry.EventType;
import com.android.tradefed.log.LogRegistry;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.SizeLimitedOutputStream;
import com.android.tradefed.util.StreamUtil;
import com.android.tradefed.util.TableFormatter;
import com.android.tradefed.util.ZipUtil2;
import com.android.tradefed.util.hostmetric.IHostMonitor;

import com.google.common.annotations.VisibleForTesting;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@OptionClass(alias = "dmgr", global_namespace = false)
public class DeviceManager implements IDeviceManager {

    /** Display string for unknown properties */
    public static final String UNKNOWN_DISPLAY_STRING = "unknown";

    /** max wait time in ms for fastboot devices command to complete */
    private static final long FASTBOOT_CMD_TIMEOUT = 1 * 60 * 1000;
    /** time to wait in ms between fastboot devices requests */
    private static final long FASTBOOT_POLL_WAIT_TIME = 5 * 1000;
    /**
     * time to wait for device adb shell responsive connection before declaring it unavailable for
     * testing
     */
    private static final int CHECK_WAIT_DEVICE_AVAIL_MS = 30 * 1000;

    /* the max size of the emulator output in bytes */
    private static final long MAX_EMULATOR_OUTPUT = 20 * 1024 * 1024;

    /* the emulator output log name */
    private static final String EMULATOR_OUTPUT = "emulator_log";

    /** a {@link DeviceSelectionOptions} that matches any device. Visible for testing. */
    static final IDeviceSelection ANY_DEVICE_OPTIONS = new DeviceSelectionOptions();
    private static final String NULL_DEVICE_SERIAL_PREFIX = "null-device";
    private static final String EMULATOR_SERIAL_PREFIX = "emulator";
    private static final String TCP_DEVICE_SERIAL_PREFIX = "tcp-device";
    private static final String GCE_DEVICE_SERIAL_PREFIX = "gce-device";
    private static final String REMOTE_DEVICE_SERIAL_PREFIX = "remote-device";
    private static final String LOCAL_VIRTUAL_DEVICE_SERIAL_PREFIX = "local-virtual-device";

    /**
     * Pattern for a device listed by 'adb devices':
     *
     * <p>List of devices attached
     *
     * <p>serial1 device
     *
     * <p>serial2 offline
     */
    private static final String DEVICE_LIST_PATTERN = ".*\n(%s)\\s+(device|offline|recovery).*";

    private Semaphore mConcurrentFlashLock = null;

    /**
     * This serves both as an indication of whether the flash lock should be used, and as an
     * indicator of whether or not the flash lock has been initialized -- if this is true
     * and {@code mConcurrentFlashLock} is {@code null}, then it has not yet been initialized.
     */
    private Boolean mShouldCheckFlashLock = true;

    protected DeviceMonitorMultiplexer mDvcMon = new DeviceMonitorMultiplexer();
    private Boolean mDvcMonRunning = false;

    private boolean mIsInitialized = false;

    private ManagedDeviceList mManagedDeviceList;

    private IAndroidDebugBridge mAdbBridge;
    private ManagedDeviceListener mManagedDeviceListener;
    protected boolean mFastbootEnabled;
    private Set<IFastbootListener> mFastbootListeners;
    private FastbootMonitor mFastbootMonitor;
    private boolean mIsTerminated = false;
    private IDeviceSelection mGlobalDeviceFilter;
    private IDeviceSelection mDeviceSelectionOptions;

    @Option(name = "max-emulators",
            description = "the maximum number of emulators that can be allocated at one time")
    private int mNumEmulatorSupported = 1;
    @Option(name = "max-null-devices",
            description = "the maximum number of no device runs that can be allocated at one time.")
    private int mNumNullDevicesSupported = 5;
    @Option(name = "max-tcp-devices",
            description = "the maximum number of tcp devices that can be allocated at one time")
    private int mNumTcpDevicesSupported = 1;

    @Option(
        name = "max-gce-devices",
        description = "the maximum number of remote gce devices that can be allocated at one time"
    )
    private int mNumGceDevicesSupported = 1;

    @Option(
        name = "max-remote-devices",
        description = "the maximum number of remote devices that can be allocated at one time"
    )
    private int mNumRemoteDevicesSupported = 1;

    @Option(
            name = "max-local-virtual-devices",
            description =
                    "the maximum number of local virtual devices that can be allocated at one time")
    private int mNumLocalVirtualDevicesSupported = 0;

    private boolean mSynchronousMode = false;

    @Option(name = "device-recovery-interval",
            description = "the interval in ms between attempts to recover unavailable devices.",
            isTimeVal = true)
    private long mDeviceRecoveryInterval = 30 * 60 * 1000;

    @Option(name = "adb-path", description = "path of the adb binary to use, "
            + "default use the one in $PATH.")
    private String mAdbPath = "adb";

    @Option(
        name = "fastboot-path",
        description = "path of the fastboot binary to use, default use the one in $PATH."
    )
    private File mFastbootFile = new File("fastboot");

    private File mUnpackedFastbootDir = null;
    private File mUnpackedFastboot = null;

    private DeviceRecoverer mDeviceRecoverer;

    private List<IHostMonitor> mGlobalHostMonitors = null;

    /** Counter to wait for the first physical connection before proceeding **/
    private CountDownLatch mFirstDeviceAdded = new CountDownLatch(1);

    /** Flag to remember if adb bridge has been disconnected and needs to be reset * */
    private boolean mAdbBridgeNeedRestart = false;

    /**
     * The DeviceManager should be retrieved from the {@link GlobalConfiguration}
     */
    public DeviceManager() {
    }

    @Override
    public void init() {
        init(null, null);
    }

    /**
     * Initialize the device manager. This must be called once and only once before any other
     * methods are called.
     */
    @Override
    public void init(IDeviceSelection globalDeviceFilter,
            List<IDeviceMonitor> globalDeviceMonitors) {
        init(globalDeviceFilter, globalDeviceMonitors,
                new ManagedTestDeviceFactory(mFastbootEnabled, DeviceManager.this, mDvcMon));
    }

    /**
     * Initialize the device manager. This must be called once and only once before any other
     * methods are called.
     */
    public synchronized void init(IDeviceSelection globalDeviceFilter,
            List<IDeviceMonitor> globalDeviceMonitors, IManagedTestDeviceFactory deviceFactory) {
        if (mIsInitialized) {
            throw new IllegalStateException("already initialized");
        }

        if (globalDeviceFilter == null) {
            globalDeviceFilter = getGlobalConfig().getDeviceRequirements();
        }

        if (globalDeviceMonitors == null) {
            globalDeviceMonitors = getGlobalConfig().getDeviceMonitors();
        }

        mGlobalHostMonitors = getGlobalConfig().getHostMonitors();
        if (mGlobalHostMonitors != null) {
            for (IHostMonitor hm : mGlobalHostMonitors) {
                hm.start();
            }
        }

        mIsInitialized = true;
        mGlobalDeviceFilter = globalDeviceFilter;
        if (globalDeviceMonitors != null) {
            mDvcMon.addMonitors(globalDeviceMonitors);
        }
        mManagedDeviceList = new ManagedDeviceList(deviceFactory);

        // Setup fastboot- if it's zipped, unzip it
        if (".zip".equals(FileUtil.getExtension(mFastbootFile.getName()))) {
            // Unzip the fastboot files
            try {
                mUnpackedFastbootDir =
                        ZipUtil2.extractZipToTemp(mFastbootFile, "unpacked-fastboot");
                mUnpackedFastboot = FileUtil.findFile(mUnpackedFastbootDir, "fastboot");
            } catch (IOException e) {
                CLog.e("Failed to unpacked zipped fastboot.");
                CLog.e(e);
                FileUtil.recursiveDelete(mUnpackedFastbootDir);
                mUnpackedFastbootDir = null;
            }
        }

        final FastbootHelper fastboot = new FastbootHelper(getRunUtil(), getFastbootPath());
        if (fastboot.isFastbootAvailable()) {
            mFastbootListeners = Collections.synchronizedSet(new HashSet<IFastbootListener>());
            mFastbootMonitor = new FastbootMonitor();
            startFastbootMonitor();
            // don't set fastboot enabled bit until mFastbootListeners has been initialized
            mFastbootEnabled = true;
            deviceFactory.setFastbootEnabled(mFastbootEnabled);
            // Populate the fastboot devices
            // TODO: remove when refactoring fastboot handling
            addFastbootDevices();
            CLog.d("Using Fastboot from: '%s'", getFastbootPath());
        } else {
            CLog.w("Fastboot is not available.");
            mFastbootListeners = null;
            mFastbootMonitor = null;
            mFastbootEnabled = false;
            deviceFactory.setFastbootEnabled(mFastbootEnabled);
        }

        // don't start adding devices until fastboot support has been established
        startAdbBridgeAndDependentServices();
    }

    /** Initialize adb connection and services depending on adb connection. */
    private synchronized void startAdbBridgeAndDependentServices() {
        // TODO: Temporarily increase default timeout as workaround for syncFiles timeouts
        DdmPreferences.setTimeOut(120 * 1000);
        mAdbBridge = createAdbBridge();
        mManagedDeviceListener = new ManagedDeviceListener();
        // It's important to add the listener before initializing the ADB bridge to avoid a race
        // condition when detecting devices.
        mAdbBridge.addDeviceChangeListener(mManagedDeviceListener);
        if (mDvcMon != null && !mDvcMonRunning) {
            mDvcMon.setDeviceLister(
                    new DeviceLister() {
                        @Override
                        public List<DeviceDescriptor> listDevices() {
                            return listAllDevices();
                        }

                        @Override
                        public DeviceDescriptor getDeviceDescriptor(String serial) {
                            return DeviceManager.this.getDeviceDescriptor(serial);
                        }
                    });
            mDvcMon.run();
            mDvcMonRunning = true;
        }

        mAdbBridge.init(false /* client support */, mAdbPath);
        addEmulators();
        addNullDevices();
        addTcpDevices();
        addGceDevices();
        addRemoteDevices();
        addLocalVirtualDevices();
        addNetworkDevices();

        List<IMultiDeviceRecovery> recoverers = getGlobalConfig().getMultiDeviceRecoveryHandlers();
        if (recoverers != null && !recoverers.isEmpty()) {
            for (IMultiDeviceRecovery recoverer : recoverers) {
                recoverer.setFastbootPath(getFastbootPath());
            }
            mDeviceRecoverer = new DeviceRecoverer(recoverers);
            startDeviceRecoverer();
        } else {
            CLog.d("No IMultiDeviceRecovery configured.");
        }
    }


    /**
     * Return if adb bridge has been stopped and needs restart.
     *
     * <p>Exposed for unit testing.
     */
    @VisibleForTesting
    boolean shouldAdbBridgeBeRestarted() {
        return mAdbBridgeNeedRestart;
    }

    /** {@inheritDoc} */
    @Override
    public synchronized void restartAdbBridge() {
        if (mAdbBridgeNeedRestart) {
            mAdbBridgeNeedRestart = false;
            startAdbBridgeAndDependentServices();
        }
    }

    /**
     * Instruct DeviceManager whether to use background threads or not.
     * <p/>
     * Exposed to make unit tests more deterministic.
     *
     * @param syncMode
     */
    void setSynchronousMode(boolean syncMode) {
        mSynchronousMode = syncMode;
    }

    private void checkInit() {
        if (!mIsInitialized) {
            throw new IllegalStateException("DeviceManager has not been initialized");
        }
    }

    /**
     * Start fastboot monitoring.
     * <p/>
     * Exposed for unit testing.
     */
    void startFastbootMonitor() {
        mFastbootMonitor.start();
    }

    /**
     * Start device recovery.
     * <p/>
     * Exposed for unit testing.
     */
    void startDeviceRecoverer() {
        mDeviceRecoverer.start();
    }

    /**
     * Get the {@link IGlobalConfiguration} instance to use.
     * <p />
     * Exposed for unit testing.
     */
    IGlobalConfiguration getGlobalConfig() {
        return GlobalConfiguration.getInstance();
    }

    /**
     * Gets the {@link IHostOptions} instance to use.
     * <p/>
     * Exposed for unit testing
     */
    IHostOptions getHostOptions() {
        return getGlobalConfig().getHostOptions();
    }

    /**
     * Get the {@link RunUtil} instance to use.
     * <p/>
     * Exposed for unit testing.
     */
    IRunUtil getRunUtil() {
        return RunUtil.getDefault();
    }

    /**
     * Create a {@link RunUtil} instance to use.
     * <p/>
     * Exposed for unit testing.
     */
    IRunUtil createRunUtil() {
        return new RunUtil();
    }

    /**
     * Asynchronously checks if device is available, and adds to queue
     *
     * @param testDevice
     */
    private void checkAndAddAvailableDevice(final IManagedTestDevice testDevice) {
        if (mGlobalDeviceFilter != null && !mGlobalDeviceFilter.matches(testDevice.getIDevice())) {
            CLog.logAndDisplay(LogLevel.INFO, "device %s doesn't match global filter, ignoring",
                    testDevice.getSerialNumber());
            mManagedDeviceList.handleDeviceEvent(testDevice, DeviceEvent.AVAILABLE_CHECK_IGNORED);
            return;
        }

        final String threadName = String.format("Check device %s", testDevice.getSerialNumber());
        Runnable checkRunnable = new Runnable() {
            @Override
            public void run() {
                CLog.d("checking new '%s' '%s' responsiveness", testDevice.getClass().getName(),
                        testDevice.getSerialNumber());
                if (testDevice.getMonitor().waitForDeviceShell(CHECK_WAIT_DEVICE_AVAIL_MS)) {
                    DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.AVAILABLE_CHECK_PASSED);
                    if (r.stateChanged && r.allocationState == DeviceAllocationState.Available) {
                        CLog.logAndDisplay(LogLevel.INFO, "Detected new device %s",
                                testDevice.getSerialNumber());
                    } else {
                        CLog.d("Device %s failed or ignored responsiveness check, ",
                                testDevice.getSerialNumber());
                    }
                } else {
                    DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.AVAILABLE_CHECK_FAILED);
                    if (r.stateChanged && r.allocationState == DeviceAllocationState.Unavailable) {
                        CLog.w("Device %s is unresponsive, will not be available for testing",
                                testDevice.getSerialNumber());
                    }
                }
            }
        };
        if (mSynchronousMode) {
            checkRunnable.run();
        } else {
            Thread checkThread = new Thread(checkRunnable, threadName);
            // Device checking threads shouldn't hold the JVM open
            checkThread.setName("DeviceManager-checkRunnable");
            checkThread.setDaemon(true);
            checkThread.start();
        }
    }

    /**
     * Add placeholder objects for the max number of 'no device required' concurrent allocations
     */
    private void addNullDevices() {
        for (int i = 0; i < mNumNullDevicesSupported; i++) {
            addAvailableDevice(new NullDevice(String.format("%s-%d", NULL_DEVICE_SERIAL_PREFIX, i)));
        }
    }

    /**
     * Add placeholder objects for the max number of emulators that can be allocated
     */
    private void addEmulators() {
        // TODO currently this means 'additional emulators not already running'
        int port = 5554;
        for (int i = 0; i < mNumEmulatorSupported; i++) {
            addAvailableDevice(new StubDevice(String.format("%s-%d", EMULATOR_SERIAL_PREFIX, port),
                    true));
            port += 2;
        }
    }

    /**
     * Add placeholder objects for the max number of tcp devices that can be connected
     */
    private void addTcpDevices() {
        for (int i = 0; i < mNumTcpDevicesSupported; i++) {
            addAvailableDevice(new TcpDevice(String.format("%s-%d", TCP_DEVICE_SERIAL_PREFIX, i)));
        }
    }

    /** Add placeholder objects for the max number of gce devices that can be connected */
    private void addGceDevices() {
        for (int i = 0; i < mNumGceDevicesSupported; i++) {
            addAvailableDevice(
                    new RemoteAvdIDevice(String.format("%s-%d", GCE_DEVICE_SERIAL_PREFIX, i)));
        }
    }

    /** Add placeholder objects for the max number of remote devices that can be managed */
    private void addRemoteDevices() {
        for (int i = 0; i < mNumRemoteDevicesSupported; i++) {
            addAvailableDevice(
                    new VmRemoteDevice(String.format("%s-%s", REMOTE_DEVICE_SERIAL_PREFIX, i)));
        }
    }

    private void addNetworkDevices() {
        int index = mNumTcpDevicesSupported;
        for (String ip : getGlobalConfig().getHostOptions().getKnownTcpDeviceIpPool()) {
            addAvailableDevice(
                    new TcpDevice(String.format("%s-%d", TCP_DEVICE_SERIAL_PREFIX, index), ip));
            index++;
        }

        index = mNumGceDevicesSupported;
        for (String ip : getGlobalConfig().getHostOptions().getKnownGceDeviceIpPool()) {
            addAvailableDevice(
                    new RemoteAvdIDevice(
                            String.format("%s-%d", GCE_DEVICE_SERIAL_PREFIX, index), ip));
            index++;
        }
    }

    private void addLocalVirtualDevices() {
        for (int i = 0; i < mNumLocalVirtualDevicesSupported; i++) {
            addAvailableDevice(
                    new StubLocalAndroidVirtualDevice(
                            String.format("%s-%s", LOCAL_VIRTUAL_DEVICE_SERIAL_PREFIX, i)));
        }
    }

    public void addAvailableDevice(IDevice stubDevice) {
        IManagedTestDevice d = mManagedDeviceList.findOrCreate(stubDevice);
        if (d != null) {
            mManagedDeviceList.handleDeviceEvent(d, DeviceEvent.FORCE_AVAILABLE);
        } else {
            CLog.e("Could not create stub device");
        }
    }

    private void addFastbootDevices() {
        final FastbootHelper fastboot = new FastbootHelper(getRunUtil(), getFastbootPath());
        Set<String> serials = fastboot.getDevices();
        for (String serial : serials) {
            FastbootDevice d = new FastbootDevice(serial);
            if (mGlobalDeviceFilter != null && mGlobalDeviceFilter.matches(d)) {
                addAvailableDevice(d);
            }
        }
    }

    /** Representation of a device in Fastboot mode. */
    public static class FastbootDevice extends StubDevice {

        public FastbootDevice(String serial) {
            super(serial, false);
        }
    }

    /**
     * Creates a {@link IDeviceStateMonitor} to use.
     * <p/>
     * Exposed so unit tests can mock
     */
    IDeviceStateMonitor createStateMonitor(IDevice device) {
        return new DeviceStateMonitor(this, device, mFastbootEnabled);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice allocateDevice() {
        return allocateDevice(ANY_DEVICE_OPTIONS, false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice allocateDevice(IDeviceSelection options) {
        return allocateDevice(options, false);
    }

    /** {@inheritDoc} */
    @Override
    public ITestDevice allocateDevice(IDeviceSelection options, boolean isTemporary) {
        checkInit();
        if (isTemporary) {
            String rand = UUID.randomUUID().toString();
            String serial = String.format("%s%s", NullDevice.TEMP_NULL_DEVICE_PREFIX, rand);
            addAvailableDevice(new NullDevice(serial, true));
            options.setSerial(serial);
        }
        return mManagedDeviceList.allocate(options);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice forceAllocateDevice(String serial) {
        checkInit();
        IManagedTestDevice d = mManagedDeviceList.forceAllocate(serial);
        if (d != null) {
            DeviceEventResponse r = d.handleAllocationEvent(DeviceEvent.FORCE_ALLOCATE_REQUEST);
            if (r.stateChanged && r.allocationState == DeviceAllocationState.Allocated) {
                // Wait for the fastboot state to be updated once to update the IDevice.
                d.getMonitor().waitForDeviceBootloaderStateUpdate();
                return d;
            }
        }
        return null;
    }

    /**
     * Creates the {@link IAndroidDebugBridge} to use.
     * <p/>
     * Exposed so tests can mock this.
     * @return the {@link IAndroidDebugBridge}
     */
    synchronized IAndroidDebugBridge createAdbBridge() {
        return new AndroidDebugBridgeWrapper();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void freeDevice(ITestDevice device, FreeDeviceState deviceState) {
        checkInit();
        IManagedTestDevice managedDevice = (IManagedTestDevice)device;
        // force stop capturing logcat just to be sure
        managedDevice.stopLogcat();
        IDevice ideviceToReturn = device.getIDevice();
        if (ideviceToReturn instanceof NullDevice) {
            NullDevice nullDevice = (NullDevice) ideviceToReturn;
            if (nullDevice.isTemporary()) {
                DeviceEventResponse r =
                        mManagedDeviceList.handleDeviceEvent(
                                managedDevice, DeviceEvent.FREE_UNKNOWN);
                CLog.d(
                        "Temporary device '%s' final allocation state: '%s'",
                        device.getSerialNumber(), r.allocationState.toString());
                return;
            }
        }
        // don't kill emulator if it wasn't launched by launchEmulator (ie emulatorProcess is null).
        if (ideviceToReturn.isEmulator() && managedDevice.getEmulatorProcess() != null) {
            try {
                killEmulator(device);
                // stop emulator output log
                device.stopEmulatorOutput();
                // emulator killed - return a stub device
                // TODO: this is a bit of a hack. Consider having DeviceManager inject a StubDevice
                // when deviceDisconnected event is received
                ideviceToReturn = new StubDevice(ideviceToReturn.getSerialNumber(), true);
                deviceState = FreeDeviceState.AVAILABLE;
                managedDevice.setIDevice(ideviceToReturn);
            } catch (DeviceNotAvailableException e) {
                CLog.e(e);
                deviceState = FreeDeviceState.UNAVAILABLE;
            }
        }
        if (ideviceToReturn instanceof TcpDevice
                || ideviceToReturn instanceof VmRemoteDevice
                || ideviceToReturn instanceof StubLocalAndroidVirtualDevice) {
            // Make sure the device goes back to the original state.
            managedDevice.setDeviceState(TestDeviceState.NOT_AVAILABLE);
        }
        DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(managedDevice,
                getEventFromFree(managedDevice, deviceState));
        if (r != null && !r.stateChanged) {
            CLog.e("Device %s was in unexpected state %s when freeing", device.getSerialNumber(),
                    r.allocationState.toString());
        }
    }

    /**
     * Helper method to convert from a {@link com.android.tradefed.device.FreeDeviceState} to a
     * {@link com.android.tradefed.device.DeviceEvent}
     *
     * @param managedDevice
     */
    private DeviceEvent getEventFromFree(
            IManagedTestDevice managedDevice, FreeDeviceState deviceState) {
        switch (deviceState) {
            case UNRESPONSIVE:
                return DeviceEvent.FREE_UNRESPONSIVE;
            case AVAILABLE:
                return DeviceEvent.FREE_AVAILABLE;
            case UNAVAILABLE:
                // We double check if device is still showing in adb or not to confirm the
                // connection is gone.
                if (TestDeviceState.NOT_AVAILABLE.equals(managedDevice.getDeviceState())) {
                    String devices = executeGlobalAdbCommand("devices");
                    Pattern p =
                            Pattern.compile(
                                    String.format(
                                            DEVICE_LIST_PATTERN, managedDevice.getSerialNumber()));
                    if (devices == null || !p.matcher(devices).find()) {
                        return DeviceEvent.FREE_UNKNOWN;
                    }
                }
                return DeviceEvent.FREE_UNAVAILABLE;
            case IGNORE:
                return DeviceEvent.FREE_UNKNOWN;
        }
        throw new IllegalStateException("unknown FreeDeviceState");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void launchEmulator(ITestDevice device, long bootTimeout, IRunUtil runUtil,
            List<String> emulatorArgs)
            throws DeviceNotAvailableException {
        if (!device.getIDevice().isEmulator()) {
            throw new IllegalStateException(String.format("Device %s is not an emulator",
                    device.getSerialNumber()));
        }
        if (!device.getDeviceState().equals(TestDeviceState.NOT_AVAILABLE)) {
            throw new IllegalStateException(String.format(
                    "Emulator device %s is in state %s. Expected: %s", device.getSerialNumber(),
                    device.getDeviceState(), TestDeviceState.NOT_AVAILABLE));
        }
        List<String> fullArgs = new ArrayList<String>(emulatorArgs);

        try {
            CLog.i("launching emulator with %s", fullArgs.toString());
            SizeLimitedOutputStream emulatorOutput = new SizeLimitedOutputStream(
                    MAX_EMULATOR_OUTPUT, EMULATOR_OUTPUT, ".txt");
            Process p = runUtil.runCmdInBackground(fullArgs, emulatorOutput);
            // sleep a small amount to wait for process to start successfully
            getRunUtil().sleep(500);
            assertEmulatorProcessAlive(p, device);
            TestDevice testDevice = (TestDevice) device;
            testDevice.setEmulatorProcess(p);
            testDevice.setEmulatorOutputStream(emulatorOutput);
        } catch (IOException e) {
            // TODO: is this the most appropriate exception to throw?
            throw new DeviceNotAvailableException("Failed to start emulator process", e,
                    device.getSerialNumber());
        }

        device.waitForDeviceAvailable(bootTimeout);
    }

    private void assertEmulatorProcessAlive(Process p, ITestDevice device)
            throws DeviceNotAvailableException {
        if (!p.isAlive()) {
            try {
                CLog.e("Emulator process has died . stdout: '%s', stderr: '%s'",
                        StreamUtil.getStringFromStream(p.getInputStream()),
                        StreamUtil.getStringFromStream(p.getErrorStream()));
            } catch (IOException e) {
                // ignore
            }
            throw new DeviceNotAvailableException("emulator died after launch",
                    device.getSerialNumber());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void killEmulator(ITestDevice device) throws DeviceNotAvailableException {
        EmulatorConsole console = EmulatorConsole.getConsole(device.getIDevice());
        if (console != null) {
            console.kill();
            // check and wait for device to become not avail
            device.waitForDeviceNotAvailable(5 * 1000);
            // lets ensure process is killed too - fall through
        } else {
            CLog.w("Could not get emulator console for %s", device.getSerialNumber());
        }
        // lets try killing the process
        Process emulatorProcess = ((IManagedTestDevice) device).getEmulatorProcess();
        if (emulatorProcess != null) {
            emulatorProcess.destroy();
            if (emulatorProcess.isAlive()) {
                CLog.w("Emulator process still running after destroy for %s",
                        device.getSerialNumber());
                forceKillProcess(emulatorProcess, device.getSerialNumber());
            }
        }
        if (!device.waitForDeviceNotAvailable(20 * 1000)) {
            throw new DeviceNotAvailableException(String.format("Failed to kill emulator %s",
                    device.getSerialNumber()), device.getSerialNumber());
        }
    }

    /**
     * Disgusting hack alert! Attempt to force kill given process.
     * Relies on implementation details. Only works on linux
     *
     * @param emulatorProcess the {@link Process} to kill
     * @param emulatorSerial the serial number of emulator. Only used for logging
     */
    private void forceKillProcess(Process emulatorProcess, String emulatorSerial) {
        if (emulatorProcess.getClass().getName().equals("java.lang.UNIXProcess")) {
            try {
                CLog.i("Attempting to force kill emulator process for %s", emulatorSerial);
                Field f = emulatorProcess.getClass().getDeclaredField("pid");
                f.setAccessible(true);
                Integer pid = (Integer)f.get(emulatorProcess);
                if (pid != null) {
                    RunUtil.getDefault().runTimedCmd(5 * 1000, "kill", "-9", pid.toString());
                }
            } catch (NoSuchFieldException e) {
                CLog.d("got NoSuchFieldException when attempting to read process pid");
            } catch (IllegalAccessException e) {
                CLog.d("got IllegalAccessException when attempting to read process pid");
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice connectToTcpDevice(String ipAndPort) {
        IManagedTestDevice tcpDevice = mManagedDeviceList.findOrCreate(new StubDevice(ipAndPort));
        if (tcpDevice == null) {
            return null;
        }
        DeviceEventResponse r = tcpDevice.handleAllocationEvent(DeviceEvent.FORCE_ALLOCATE_REQUEST);
        if (r.stateChanged && r.allocationState == DeviceAllocationState.Allocated) {
            // Wait for the fastboot state to be updated once to update the IDevice.
            tcpDevice.getMonitor().waitForDeviceBootloaderStateUpdate();
        } else {
            return null;
        }
        if (doAdbConnect(ipAndPort)) {
            try {
                tcpDevice.setRecovery(new WaitDeviceRecovery());
                tcpDevice.waitForDeviceOnline();
                return tcpDevice;
            } catch (DeviceNotAvailableException e) {
                CLog.w("Device with tcp serial %s did not come online", ipAndPort);
            }
        }
        freeDevice(tcpDevice, FreeDeviceState.IGNORE);
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ITestDevice reconnectDeviceToTcp(ITestDevice usbDevice)
            throws DeviceNotAvailableException {
        CLog.i("Reconnecting device %s to adb over tcpip", usbDevice.getSerialNumber());
        ITestDevice tcpDevice = null;
        if (usbDevice instanceof IManagedTestDevice) {
            IManagedTestDevice managedUsbDevice = (IManagedTestDevice) usbDevice;
            String ipAndPort = managedUsbDevice.switchToAdbTcp();
            if (ipAndPort != null) {
                CLog.d("Device %s was switched to adb tcp on %s", usbDevice.getSerialNumber(),
                        ipAndPort);
                tcpDevice = connectToTcpDevice(ipAndPort);
                if (tcpDevice == null) {
                    // ruh roh, could not connect to device
                    // Try to re-establish connection back to usb device
                    managedUsbDevice.recoverDevice();
                }
            }
        } else {
            CLog.e("reconnectDeviceToTcp: unrecognized device type.");
        }
        return tcpDevice;
    }

    @Override
    public boolean disconnectFromTcpDevice(ITestDevice tcpDevice) {
        CLog.i("Disconnecting and freeing tcp device %s", tcpDevice.getSerialNumber());
        boolean result = false;
        try {
            result = tcpDevice.switchToAdbUsb();
        } catch (DeviceNotAvailableException e) {
            CLog.w("Failed to switch device %s to usb mode: %s", tcpDevice.getSerialNumber(),
                    e.getMessage());
        }
        freeDevice(tcpDevice, FreeDeviceState.IGNORE);
        return result;
    }

    private boolean doAdbConnect(String ipAndPort) {
        final String resultSuccess = String.format("connected to %s", ipAndPort);
        for (int i = 1; i <= 3; i++) {
            String adbConnectResult = executeGlobalAdbCommand("connect", ipAndPort);
            // runcommand "adb connect ipAndPort"
            if (adbConnectResult != null && adbConnectResult.startsWith(resultSuccess)) {
                return true;
            }
            CLog.w("Failed to connect to device on %s, attempt %d of 3. Response: %s.",
                    ipAndPort, i, adbConnectResult);
            getRunUtil().sleep(5 * 1000);
        }
        return false;
    }

    /**
     * Execute a adb command not targeted to a particular device eg. 'adb connect'
     *
     * @param cmdArgs
     * @return std output if the command succeedm null otherwise.
     */
    public String executeGlobalAdbCommand(String... cmdArgs) {
        String[] fullCmd = ArrayUtil.buildArray(new String[] {getAdbPath()}, cmdArgs);
        CommandResult result = getRunUtil().runTimedCmd(FASTBOOT_CMD_TIMEOUT, fullCmd);
        if (CommandStatus.SUCCESS.equals(result.getStatus())) {
            return result.getStdout();
        }
        CLog.w("adb %s failed", cmdArgs[0]);
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void terminate() {
        checkInit();
        if (!mIsTerminated) {
            mIsTerminated = true;
            stopAdbBridgeAndDependentServices();
            // We are not terminating mFastbootMonitor here since it is a daemon thread.
            // Early terminating it can cause other threads to be blocked if they check
            // fastboot state of a device.
            if (mGlobalHostMonitors != null ) {
                for (IHostMonitor hm : mGlobalHostMonitors) {
                    hm.terminate();
                }
            }
        }
        FileUtil.recursiveDelete(mUnpackedFastbootDir);
    }

    /** Stop adb bridge and services depending on adb connection. */
    private synchronized void stopAdbBridgeAndDependentServices() {
        terminateDeviceRecovery();
        mAdbBridge.removeDeviceChangeListener(mManagedDeviceListener);
        mAdbBridge.terminate();
    }

    /** {@inheritDoc} */
    @Override
    public synchronized void stopAdbBridge() {
        stopAdbBridgeAndDependentServices();
        mAdbBridgeNeedRestart = true;
    }

    /** {@inheritDoc} */
    @Override
    public synchronized void terminateDeviceRecovery() {
        if (mDeviceRecoverer != null) {
            mDeviceRecoverer.terminate();
        }
    }

    /** {@inheritDoc} */
    @Override
    public synchronized void terminateDeviceMonitor() {
        mDvcMon.stop();
    }

    /** {@inheritDoc} */
    @Override
    public synchronized void terminateHard() {
        checkInit();
        if (!mIsTerminated ) {
            for (IManagedTestDevice device : mManagedDeviceList) {
                device.setRecovery(new AbortRecovery());
            }
            mAdbBridge.disconnectBridge();
            terminate();
        }
    }

    private static class AbortRecovery implements IDeviceRecovery {

        /**
         * {@inheritDoc}
         */
        @Override
        public void recoverDevice(IDeviceStateMonitor monitor, boolean recoverUntilOnline)
                throws DeviceNotAvailableException {
            throw new DeviceNotAvailableException("aborted test session",
                    monitor.getSerialNumber());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void recoverDeviceBootloader(IDeviceStateMonitor monitor)
                throws DeviceNotAvailableException {
            throw new DeviceNotAvailableException("aborted test session",
                    monitor.getSerialNumber());
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void recoverDeviceRecovery(IDeviceStateMonitor monitor)
                throws DeviceNotAvailableException {
            throw new DeviceNotAvailableException("aborted test session",
                    monitor.getSerialNumber());
        }

        /** {@inheritDoc} */
        @Override
        public void recoverDeviceFastbootd(IDeviceStateMonitor monitor)
                throws DeviceNotAvailableException {
            throw new DeviceNotAvailableException(
                    "aborted test session", monitor.getSerialNumber());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<DeviceDescriptor> listAllDevices() {
        final List<DeviceDescriptor> serialStates = new ArrayList<DeviceDescriptor>();
        if (mAdbBridgeNeedRestart) {
            return serialStates;
        }
        for (IManagedTestDevice d : mManagedDeviceList) {
            if (d == null) {
                continue;
            }
            DeviceDescriptor desc = d.getCachedDeviceDescriptor();
            if (desc != null) {
                serialStates.add(desc);
            }
        }
        return serialStates;
    }

    /** {@inheritDoc} */
    @Override
    public DeviceDescriptor getDeviceDescriptor(String serial) {
        IManagedTestDevice device = mManagedDeviceList.find(serial);
        if (device == null) {
            return null;
        }
        return device.getDeviceDescriptor();
    }

    @Override
    public void displayDevicesInfo(PrintWriter stream, boolean includeStub) {
        List<List<String>> displayRows = new ArrayList<List<String>>();
        List<String> headers =
                new ArrayList<>(
                        Arrays.asList(
                                "Serial",
                                "State",
                                "Allocation",
                                "Product",
                                "Variant",
                                "Build",
                                "Battery"));
        if (includeStub) {
            headers.add("class");
            headers.add("TestDeviceState");
        }
        displayRows.add(headers);
        List<DeviceDescriptor> deviceList = listAllDevices();
        sortDeviceList(deviceList);
        addDevicesInfo(displayRows, deviceList, includeStub);
        new TableFormatter().displayTable(displayRows, stream);
    }

    /**
     * Sorts list by state, then by serial.
     */
    @VisibleForTesting
    static List<DeviceDescriptor> sortDeviceList(List<DeviceDescriptor> deviceList) {

        Comparator<DeviceDescriptor> c = new Comparator<DeviceDescriptor>() {

            @Override
            public int compare(DeviceDescriptor o1, DeviceDescriptor o2) {
                if (o1.getState() != o2.getState()) {
                    // sort by state
                    return o1.getState().toString()
                            .compareTo(o2.getState().toString());
                }
                // states are equal, sort by serial
                return o1.getSerial().compareTo(o2.getSerial());
            }

        };
        Collections.sort(deviceList, c);
        return deviceList;
    }

    /**
     * Get the {@link IDeviceSelection} to use to display device info
     *
     * <p>Exposed for unit testing.
     */
    IDeviceSelection getDeviceSelectionOptions() {
        if (mDeviceSelectionOptions == null) {
            mDeviceSelectionOptions = new DeviceSelectionOptions();
        }
        return mDeviceSelectionOptions;
    }

    private void addDevicesInfo(
            List<List<String>> displayRows,
            List<DeviceDescriptor> sortedDeviceList,
            boolean includeStub) {
        for (DeviceDescriptor desc : sortedDeviceList) {
            if (!includeStub) {
                if (desc.isStubDevice() && desc.getState() != DeviceAllocationState.Allocated) {
                    // don't add placeholder devices
                    continue;
                }
            }
            String serial = desc.getSerial();
            if (desc.getDisplaySerial() != null) {
                serial = desc.getDisplaySerial();
            }
            List<String> infos =
                    new ArrayList<>(
                            Arrays.asList(
                                    serial,
                                    desc.getDeviceState().toString(),
                                    desc.getState().toString(),
                                    desc.getProduct(),
                                    desc.getProductVariant(),
                                    desc.getBuildId(),
                                    desc.getBatteryLevel()));
            if (includeStub) {
                infos.add(desc.getDeviceClass());
                infos.add(desc.getTestDeviceState().toString());
            }
            displayRows.add(infos);
        }
    }

    /**
     * A class to listen for and act on device presence updates from ddmlib
     */
    private class ManagedDeviceListener implements IDeviceChangeListener {

        /**
         * {@inheritDoc}
         */
        @Override
        public void deviceChanged(IDevice idevice, int changeMask) {
            if ((changeMask & IDevice.CHANGE_STATE) != 0) {
                IManagedTestDevice testDevice = mManagedDeviceList.findOrCreate(idevice);
                if (testDevice == null) {
                    return;
                }
                TestDeviceState newState = TestDeviceState.getStateByDdms(idevice.getState());
                testDevice.setDeviceState(newState);
                if (newState == TestDeviceState.ONLINE) {
                    DeviceEventResponse r = mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.STATE_CHANGE_ONLINE);
                    if (r.stateChanged && r.allocationState ==
                            DeviceAllocationState.Checking_Availability) {
                        checkAndAddAvailableDevice(testDevice);
                    }
                } else if (DeviceState.OFFLINE.equals(idevice.getState()) ||
                        DeviceState.UNAUTHORIZED.equals(idevice.getState())) {
                    // handle device changing to offline or unauthorized.
                    mManagedDeviceList.handleDeviceEvent(testDevice,
                            DeviceEvent.STATE_CHANGE_OFFLINE);
                }
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void deviceConnected(IDevice idevice) {
            CLog.d("Detected device connect %s, id %d", idevice.getSerialNumber(),
                    idevice.hashCode());
            String threadName = String.format("Connected device %s", idevice.getSerialNumber());
            Runnable connectedRunnable =
                    new Runnable() {
                        @Override
                        public void run() {
                            IManagedTestDevice testDevice =
                                    mManagedDeviceList.findOrCreate(idevice);
                            if (testDevice == null) {
                                return;
                            }
                            // DDMS will allocate a new IDevice, so need
                            // to update the TestDevice record with the new device
                            CLog.d("Updating IDevice for device %s", idevice.getSerialNumber());
                            testDevice.setIDevice(idevice);
                            TestDeviceState newState =
                                    TestDeviceState.getStateByDdms(idevice.getState());
                            testDevice.setDeviceState(newState);
                            if (newState == TestDeviceState.ONLINE) {
                                DeviceEventResponse r =
                                        mManagedDeviceList.handleDeviceEvent(
                                                testDevice, DeviceEvent.CONNECTED_ONLINE);
                                if (r.stateChanged
                                        && r.allocationState
                                                == DeviceAllocationState.Checking_Availability) {
                                    checkAndAddAvailableDevice(testDevice);
                                }
                                logDeviceEvent(
                                        EventType.DEVICE_CONNECTED, testDevice.getSerialNumber());
                            } else if (DeviceState.OFFLINE.equals(idevice.getState())
                                    || DeviceState.UNAUTHORIZED.equals(idevice.getState())) {
                                mManagedDeviceList.handleDeviceEvent(
                                        testDevice, DeviceEvent.CONNECTED_OFFLINE);
                                logDeviceEvent(
                                        EventType.DEVICE_CONNECTED_OFFLINE,
                                        testDevice.getSerialNumber());
                            }
                            mFirstDeviceAdded.countDown();
                        }
                    };

            if (mSynchronousMode) {
                connectedRunnable.run();
            } else {
                // Device creation step can take a little bit of time, so do it in a thread to
                // avoid blocking following events of new devices
                Thread checkThread = new Thread(connectedRunnable, threadName);
                // Device checking threads shouldn't hold the JVM open
                checkThread.setDaemon(true);
                checkThread.start();
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void deviceDisconnected(IDevice disconnectedDevice) {
            IManagedTestDevice d = mManagedDeviceList.find(disconnectedDevice.getSerialNumber());
            if (d != null) {
                mManagedDeviceList.handleDeviceEvent(d, DeviceEvent.DISCONNECTED);
                d.setDeviceState(TestDeviceState.NOT_AVAILABLE);
                logDeviceEvent(EventType.DEVICE_DISCONNECTED, disconnectedDevice.getSerialNumber());
            }
        }
    }

    @VisibleForTesting
    void logDeviceEvent(EventType event, String serial) {
        Map<String, String> args = new HashMap<>();
        args.put("serial", serial);
        LogRegistry.getLogRegistry().logEvent(LogLevel.DEBUG, event, args);
    }

    /** {@inheritDoc} */
    @Override
    public boolean waitForFirstDeviceAdded(long timeout) {
        try {
            return mFirstDeviceAdded.await(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addFastbootListener(IFastbootListener listener) {
        checkInit();
        if (mFastbootEnabled) {
            mFastbootListeners.add(listener);
        } else {
            throw new UnsupportedOperationException("fastboot is not enabled");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeFastbootListener(IFastbootListener listener) {
        checkInit();
        if (mFastbootEnabled) {
            mFastbootListeners.remove(listener);
        }
    }

    /**
     * A class to monitor and update fastboot state of devices.
     */
    private class FastbootMonitor extends Thread {

        private boolean mQuit = false;

        FastbootMonitor() {
            super("FastbootMonitor");
            setDaemon(true);
        }

        @Override
        public void interrupt() {
            mQuit = true;
            super.interrupt();
        }

        @Override
        public void run() {
            final FastbootHelper fastboot = new FastbootHelper(getRunUtil(), getFastbootPath());
            while (!mQuit) {
                Set<String> serials = fastboot.getDevices();
                if (serials != null) {
                    // Update known fastboot devices state
                    mManagedDeviceList.updateFastbootStates(serials, /* fastbootd */ false);
                    // Add new fastboot devices.
                    for (String serial : serials) {
                        FastbootDevice d = new FastbootDevice(serial);
                        if (mGlobalDeviceFilter != null && mGlobalDeviceFilter.matches(d)) {
                            addAvailableDevice(d);
                        }
                    }
                }
                if (!mFastbootListeners.isEmpty()) {
                    // create a copy of listeners for notification to prevent deadlocks
                    Collection<IFastbootListener> listenersCopy =
                            new ArrayList<IFastbootListener>(mFastbootListeners.size());
                    listenersCopy.addAll(mFastbootListeners);
                    for (IFastbootListener listener : listenersCopy) {
                        listener.stateUpdated();
                    }
                }
                getRunUtil().sleep(FASTBOOT_POLL_WAIT_TIME);
            }
        }
    }

    /**
     * A class for a thread which performs periodic device recovery operations.
     */
    private class DeviceRecoverer extends Thread {

        private boolean mQuit = false;
        private List<IMultiDeviceRecovery> mMultiDeviceRecoverers;

        public DeviceRecoverer(List<IMultiDeviceRecovery> multiDeviceRecoverers) {
            super("DeviceRecoverer");
            mMultiDeviceRecoverers = multiDeviceRecoverers;
            // Ensure that this thread doesn't prevent TF from terminating
            setDaemon(true);
        }

        @Override
        public void run() {
            while (!mQuit) {
                getRunUtil().sleep(mDeviceRecoveryInterval);
                if (mQuit) {
                    // After the sleep time, we check if we should run or not.
                    return;
                }
                CLog.d("Running DeviceRecoverer ...");
                if (mMultiDeviceRecoverers != null && !mMultiDeviceRecoverers.isEmpty()) {
                    for (IMultiDeviceRecovery m : mMultiDeviceRecoverers) {
                        CLog.d(
                                "Triggering IMultiDeviceRecovery class %s ...",
                                m.getClass().getSimpleName());
                        try {
                            m.recoverDevices(getDeviceList());
                        } catch (RuntimeException e) {
                            CLog.e("Exception during %s recovery:", m.getClass().getSimpleName());
                            CLog.e(e);
                            // TODO: Log this to the history events.
                        }
                    }
                }
            }
        }

        public void terminate() {
            mQuit = true;
            interrupt();
        }
    }

    @VisibleForTesting
    List<IManagedTestDevice> getDeviceList() {
        return mManagedDeviceList.getCopy();
    }

    @VisibleForTesting
    void setMaxEmulators(int numEmulators) {
        mNumEmulatorSupported = numEmulators;
    }

    @VisibleForTesting
    void setMaxNullDevices(int nullDevices) {
        mNumNullDevicesSupported = nullDevices;
    }

    @VisibleForTesting
    void setMaxTcpDevices(int tcpDevices) {
        mNumTcpDevicesSupported = tcpDevices;
    }

    @VisibleForTesting
    void setMaxGceDevices(int gceDevices) {
        mNumGceDevicesSupported = gceDevices;
    }

    @VisibleForTesting
    void setMaxRemoteDevices(int remoteDevices) {
        mNumRemoteDevicesSupported = remoteDevices;
    }

    @Override
    public boolean isNullDevice(String serial) {
        return serial.startsWith(NULL_DEVICE_SERIAL_PREFIX);
    }

    @Override
    public boolean isEmulator(String serial) {
        return serial.startsWith(EMULATOR_SERIAL_PREFIX);
    }

    @Override
    public void addDeviceMonitor(IDeviceMonitor mon) {
        mDvcMon.addMonitor(mon);
    }

    @Override
    public void removeDeviceMonitor(IDeviceMonitor mon) {
        mDvcMon.removeMonitor(mon);
    }

    @Override
    public String getAdbPath() {
        return mAdbPath;
    }

    @Override
    public String getFastbootPath() {
        if (mUnpackedFastboot != null) {
            return mUnpackedFastboot.getAbsolutePath();
        }
        // Support default fastboot in PATH variable
        if (new File("fastboot").equals(mFastbootFile)) {
            return "fastboot";
        }
        return mFastbootFile.getAbsolutePath();
    }

    /**
     * Set the state of the concurrent flash limit implementation
     *
     * Exposed for unit testing
     */
    void setConcurrentFlashSettings(Semaphore flashLock, boolean shouldCheck) {
        synchronized (mShouldCheckFlashLock) {
            mConcurrentFlashLock = flashLock;
            mShouldCheckFlashLock = shouldCheck;
        }
    }

    Semaphore getConcurrentFlashLock() {
        return mConcurrentFlashLock;
    }

    /** Initialize the concurrent flash lock semaphore **/
    private void initConcurrentFlashLock() {
        if (!mShouldCheckFlashLock) return;
        // The logic below is to avoid multi-thread race conditions while initializing
        // mConcurrentFlashLock when we hit this condition.
        if (mConcurrentFlashLock == null) {
            // null with mShouldCheckFlashLock == true means initialization hasn't been done yet
            synchronized(mShouldCheckFlashLock) {
                // Check all state again, since another thread might have gotten here first
                if (!mShouldCheckFlashLock) return;

                IHostOptions hostOptions = getHostOptions();
                Integer concurrentFlashingLimit = hostOptions.getConcurrentFlasherLimit();

                if (concurrentFlashingLimit == null) {
                    mShouldCheckFlashLock = false;
                    return;
                }

                if (mConcurrentFlashLock == null) {
                    mConcurrentFlashLock = new Semaphore(concurrentFlashingLimit, true /* fair */);
                }
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public int getAvailableFlashingPermits() {
        initConcurrentFlashLock();
        if (mConcurrentFlashLock != null) {
            return mConcurrentFlashLock.availablePermits();
        }
        IHostOptions hostOptions = getHostOptions();
        if (hostOptions.getConcurrentFlasherLimit() != null) {
            return hostOptions.getConcurrentFlasherLimit();
        }
        return Integer.MAX_VALUE;
    }

    /** {@inheritDoc} */
    @Override
    public void takeFlashingPermit() {
        initConcurrentFlashLock();
        if (!mShouldCheckFlashLock) return;

        IHostOptions hostOptions = getHostOptions();
        Integer concurrentFlashingLimit = hostOptions.getConcurrentFlasherLimit();
        CLog.i(
                "Requesting a flashing permit out of the max limit of %s. Current queue "
                        + "length: %s",
                concurrentFlashingLimit,
                mConcurrentFlashLock.getQueueLength());
        mConcurrentFlashLock.acquireUninterruptibly();
    }

    /** {@inheritDoc} */
    @Override
    public void returnFlashingPermit() {
        if (mConcurrentFlashLock != null) {
            mConcurrentFlashLock.release();
        }
    }

    /** {@inheritDoc} */
    @Override
    public String getAdbVersion() {
        return mAdbBridge.getAdbVersion(mAdbPath);
    }
}
