/*
 * Copyright (C) 2016 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.AdbCommandRejectedException;
import com.android.ddmlib.FileListingService;
import com.android.ddmlib.FileListingService.FileEntry;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
import com.android.ddmlib.SyncException.SyncError;
import com.android.ddmlib.SyncService;
import com.android.ddmlib.TimeoutException;
import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.command.remote.DeviceDescriptor;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.GlobalConfiguration;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.IConfigurationReceiver;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.IWifiHelper.WifiConnectionResult;
import com.android.tradefed.device.cloud.GceAvdInfo;
import com.android.tradefed.device.connection.AbstractConnection;
import com.android.tradefed.device.connection.DefaultConnection;
import com.android.tradefed.device.connection.DefaultConnection.ConnectionBuilder;
import com.android.tradefed.device.contentprovider.ContentProviderHandler;
import com.android.tradefed.error.HarnessRuntimeException;
import com.android.tradefed.host.IHostOptions;
import com.android.tradefed.invoker.logger.InvocationMetricLogger;
import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
import com.android.tradefed.invoker.tracing.CloseableTraceScope;
import com.android.tradefed.log.ITestLogger;
import com.android.tradefed.log.LogUtil;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.ITestLifeCycleReceiver;
import com.android.tradefed.result.ITestLoggerReceiver;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.SnapshotInputStreamSource;
import com.android.tradefed.result.StubTestRunListener;
import com.android.tradefed.result.ddmlib.TestRunToTestInvocationForwarder;
import com.android.tradefed.result.error.DeviceErrorIdentifier;
import com.android.tradefed.result.error.InfraErrorIdentifier;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.testtype.coverage.CoverageOptions.Toolchain;
import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.Bugreport;
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.KeyguardControllerState;
import com.android.tradefed.util.MultiMap;
import com.android.tradefed.util.ProcessInfo;
import com.android.tradefed.util.QuotationAwareTokenizer;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.SizeLimitedOutputStream;
import com.android.tradefed.util.StringEscapeUtils;
import com.android.tradefed.util.SystemUtil;
import com.android.tradefed.util.TimeUtil;
import com.android.tradefed.util.ZipUtil2;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.FormatMethod;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;

/** Default implementation of a {@link ITestDevice} Non-full stack android devices. */
public class NativeDevice
        implements IManagedTestDevice, IConfigurationReceiver, ITestLoggerReceiver {

    protected static final String SD_CARD = "/sdcard/";
    protected static final String STORAGE_EMULATED = "/storage/emulated/";

    /** On-device path where we expect ANRs to be generated. */
    private static final String ANRS_PATH = "/data/anr";

    /**
     * Allow up to 2 minutes to receives the full logcat dump.
     */
    private static final int LOGCAT_DUMP_TIMEOUT = 2 * 60 * 1000;

    /** the default number of command retry attempts to perform */
    protected static final int MAX_RETRY_ATTEMPTS = 2;

    /** Value returned for any invalid/not found user id: UserHandle defined the -10000 value */
    public static final int INVALID_USER_ID = -10000;

    /** regex to match input dispatch readiness line **/
    static final Pattern INPUT_DISPATCH_STATE_REGEX =
            Pattern.compile("DispatchEnabled:\\s?([01])");
    /** regex to match build signing key type */
    private static final Pattern KEYS_PATTERN = Pattern.compile("^.*-keys$");

    private static final Pattern DF_PATTERN =
            Pattern.compile(
                    // Fs 1K-blks Used    Available Use%      Mounted on
                    "^/(\\S+)\\s+\\d+\\s+\\d+\\s+(\\d+)\\s+\\d+%\\s+/\\S*$", Pattern.MULTILINE);

    protected static final long MAX_HOST_DEVICE_TIME_OFFSET = 5 * 1000;

    /** The password for encrypting and decrypting the device. */
    private static final String ENCRYPTION_PASSWORD = "android";

    /** The maximum system_server start delay in seconds after device boot up */
    private static final int MAX_SYSTEM_SERVER_DELAY_AFTER_BOOT_UP_SEC = 25;

    /** The time in ms to wait before starting logcat for a device */
    private int mLogStartDelay = 5*1000;

    /** The time in ms to wait for a device to become unavailable. Should usually be short */
    private static final int DEFAULT_UNAVAILABLE_TIMEOUT = 20 * 1000;

    private static final String SIM_STATE_PROP = "gsm.sim.state";
    private static final String SIM_OPERATOR_PROP = "gsm.operator.alpha";

    static final String MAC_ADDRESS_PATTERN = "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
    static final String MAC_ADDRESS_COMMAND = "su root cat /sys/class/net/wlan0/address";
    static final String ETHERNET_MAC_ADDRESS_COMMAND = "cat /sys/class/net/eth0/address";

    static final int ETHER_ADDR_LEN = 6;

    /** The network monitoring interval in ms. */
    private static final int NETWORK_MONITOR_INTERVAL = 10 * 1000;

    /** Wifi reconnect check interval in ms. */
    private static final int WIFI_RECONNECT_CHECK_INTERVAL = 1 * 1000;

    /** Wifi reconnect timeout in ms. */
    private static final int WIFI_RECONNECT_TIMEOUT = 60 * 1000;

    /** Pattern to find an executable file. */
    private static final Pattern EXE_FILE = Pattern.compile("^[-l]r.x.+");

    /** Path of the device containing the tombstones */
    private static final String TOMBSTONE_PATH = "/data/tombstones/";

    private static final long PROPERTY_GET_TIMEOUT = 45 * 1000L;

    public static final String DEBUGFS_PATH = "/sys/kernel/debug";
    private static final String CHECK_DEBUGFS_MNT_COMMAND =
            String.format("mountpoint -q %s", DEBUGFS_PATH);
    private static final String MOUNT_DEBUGFS_COMMAND =
            String.format("mount -t debugfs debugfs %s", DEBUGFS_PATH);
    private static final String UNMOUNT_DEBUGFS_COMMAND = String.format("umount %s", DEBUGFS_PATH);

    /** Version number for a current development build */
    private static final int CUR_DEVELOPMENT_VERSION = 10000;

    /** The time in ms to wait for a 'long' command to complete. */
    private long mLongCmdTimeout = 25 * 60 * 1000L;



    /**
     * The delimiter that separates the actual shell output and the exit status.
     *
     * <p>Used to determine the exit status of the command run by adb shell for devices that do not
     * support shell_v2.
     */
    private static final String EXIT_STATUS_DELIMITER = "x";

    private IConfiguration mConfiguration;
    private IDevice mIDevice;
    private IDeviceRecovery mRecovery = new WaitDeviceRecovery();
    protected final IDeviceStateMonitor mStateMonitor;
    private TestDeviceState mState = TestDeviceState.ONLINE;
    private final ReentrantLock mFastbootLock = new ReentrantLock();
    private LogcatReceiver mLogcatReceiver;
    private boolean mFastbootEnabled = true;
    private String mFastbootPath = "fastboot";

    protected TestDeviceOptions mOptions = new TestDeviceOptions();
    private Process mEmulatorProcess;
    private SizeLimitedOutputStream mEmulatorOutput;
    private Clock mClock = Clock.systemUTC();

    private RecoveryMode mRecoveryMode = RecoveryMode.AVAILABLE;

    private Boolean mIsEncryptionSupported = null;
    private ReentrantLock mAllocationStateLock = new ReentrantLock(true /*fair*/);

    @GuardedBy("mAllocationStateLock")
    private DeviceAllocationState mAllocationState = DeviceAllocationState.Unknown;
    private IDeviceMonitor mAllocationMonitor = null;

    private String mLastConnectedWifiSsid = null;
    private String mLastConnectedWifiPsk = null;
    private boolean mNetworkMonitorEnabled = false;

    private ContentProviderHandler mContentProvider = null;
    private boolean mShouldSkipContentProviderSetup = false;
    /** Keep track of the last time Tradefed itself triggered a reboot. */
    private long mLastTradefedRebootTime = 0L;

    private File mExecuteShellCommandLogs = null;

    private DeviceDescriptor mCachedDeviceDescriptor = null;
    private final Object mCacheLock = new Object();

    private String mFastbootSerialNumber = null;
    private File mUnpackedFastbootDir = null;
    // Connection for the device.
    private AbstractConnection mConnection;
    private GceAvdInfo mConnectionAvd;

    private ITestLogger mTestLogger;

    private List<IDeviceActionReceiver> mDeviceActionReceivers = new LinkedList<>();
    /**
     * Whether callback for reboot is currently executing or not. Use this flag to avoid dead loop
     * scenarios like calling reboot inside a callback happening for reboot.
     */
    private boolean inRebootCallback = false;

    /** If the device is a Microdroid, this refers to the VM process. Otherwise, it is null. */
    private Process mMicrodroidProcess = null;

    private final LoadingCache<String, String> mPropertiesCache;

    // If we increase the number of props, then increase the cache size of mPropertiesCache.
    private final Set<String> propsToPrefetch =
            ImmutableSet.of("ro.build.version.sdk", "ro.build.version.codename", "ro.build.id");
    // Avoid caching any properties in those namespace
    private static final Set<String> NEVER_CACHE_PROPERTIES =
            ImmutableSet.of("vendor.debug", "ro.boot");

    /** Interface for a generic device communication attempt. */
    abstract interface DeviceAction {

        /**
         * Execute the device operation.
         *
         * @return <code>true</code> if operation is performed successfully, <code>false</code>
         *     otherwise
         * @throws IOException, TimeoutException, AdbCommandRejectedException,
         *     ShellCommandUnresponsiveException, InstallException, SyncException if operation
         *     terminated abnormally
         */
        public boolean run()
                throws IOException, TimeoutException, AdbCommandRejectedException,
                        ShellCommandUnresponsiveException, InstallException, SyncException,
                        DeviceNotAvailableException;
    }

    /**
     * A {@link DeviceAction} for running a OS 'adb ....' command.
     */
    protected class AdbAction implements DeviceAction {
        /** the output from the command */
        String mOutput = null;
        private String[] mCmd;
        private long mTimeout;
        private boolean mIsShellCommand;
        private Map<String, String> mEnvMap;

        AdbAction(long timeout, String[] cmd, boolean isShell, Map<String, String> envMap) {
            mTimeout = timeout;
            mCmd = cmd;
            mIsShellCommand = isShell;
            mEnvMap = envMap;
        }

        private void logExceptionAndOutput(CommandResult result) {
            CLog.w("Command exited with status: %s", result.getStatus().toString());
            CLog.w("Command stdout:\n%s\n", result.getStdout());
            CLog.w("Command stderr:\n%s\n", result.getStderr());
        }

        @Override
        public boolean run() throws TimeoutException, IOException {
            IRunUtil runUtil = getRunUtil();
            if (!mEnvMap.isEmpty()) {
                runUtil = createRunUtil();
            }
            for (String key : mEnvMap.keySet()) {
                runUtil.setEnvVariable(key, mEnvMap.get(key));
            }
            CommandResult result = runUtil.runTimedCmd(mTimeout, mCmd);
            // TODO: how to determine device not present with command failing for other reasons
            if (result.getStatus() == CommandStatus.EXCEPTION) {
                logExceptionAndOutput(result);
                throw new IOException("CommandStatus was EXCEPTION, details in host log");
            } else if (result.getStatus() == CommandStatus.TIMED_OUT) {
                logExceptionAndOutput(result);
                throw new TimeoutException("CommandStatus was TIMED_OUT, details in host log");
            } else if (result.getStatus() == CommandStatus.FAILED) {

                logExceptionAndOutput(result);
                if (mIsShellCommand) {
                    // Interpret as communication failure for shell commands
                    throw new IOException("CommandStatus was FAILED, details in host log");
                } else {
                    mOutput = result.getStdout();
                    return false;
                }
            }
            mOutput = result.getStdout();
            return true;
        }
    }

    protected class AdbShellAction implements DeviceAction {
        /** the output from the command */
        CommandResult mResult = null;

        private String[] mCmd;
        private long mTimeout;
        private File mPipeAsInput; // Used in pushFile, uses local file as input to "content write"
        private OutputStream mPipeToOutput; // Used in pullFile, to pipe content from "content read"
        private OutputStream mPipeToError;

        AdbShellAction(
                String[] cmd,
                File pipeAsInput,
                OutputStream pipeToOutput,
                OutputStream pipeToError,
                long timeout) {
            mCmd = cmd;
            mPipeAsInput = pipeAsInput;
            mPipeToOutput = pipeToOutput;
            mPipeToError = pipeToError;
            mTimeout = timeout;
        }

        @Override
        public boolean run() throws TimeoutException, IOException {
            if (mPipeAsInput != null) {
                mResult = getRunUtil().runTimedCmdWithInputRedirect(mTimeout, mPipeAsInput, mCmd);
            } else {
                mResult = getRunUtil().runTimedCmd(mTimeout, mPipeToOutput, mPipeToError, mCmd);
            }
            if (mResult.getStatus() == CommandStatus.EXCEPTION) {
                throw new IOException(mResult.getStderr());
            } else if (mResult.getStatus() == CommandStatus.TIMED_OUT) {
                throw new TimeoutException(mResult.getStderr());
            }
            String stdErr = mResult.getStderr();
            if (stdErr != null) {
                stdErr = stdErr.trim();
                if (stdErr.contains("device offline")) {
                    throw new IOException(stdErr);
                }
            }
            // If it's not some issue with running the adb command, then we return the CommandResult
            // which will contain all the infos.
            return true;
        }
    }

    /** {@link DeviceAction} for rebooting a device. */
    protected class RebootDeviceAction implements DeviceAction {

        private final RebootMode mRebootMode;
        @Nullable private final String mReason;

        RebootDeviceAction(RebootMode rebootMode, @Nullable String reason) {
            mRebootMode = rebootMode;
            mReason = reason;
        }

        public boolean isFastbootOrBootloader() {
            return mRebootMode == RebootMode.REBOOT_INTO_BOOTLOADER
                    || mRebootMode == RebootMode.REBOOT_INTO_FASTBOOTD;
        }

        @Override
        public boolean run()
                throws TimeoutException, IOException, AdbCommandRejectedException,
                        DeviceNotAvailableException {
            // Notify of reboot started for all modes
            notifyRebootStarted();
            getIDevice().reboot(mRebootMode.formatRebootCommand(mReason));
            return true;
        }
    }

    /**
     * Creates a {@link TestDevice}.
     *
     * @param device the associated {@link IDevice}
     * @param stateMonitor the {@link IDeviceStateMonitor} mechanism to use
     * @param allocationMonitor the {@link IDeviceMonitor} to inform of allocation state changes.
     *            Can be null
     */
    public NativeDevice(IDevice device, IDeviceStateMonitor stateMonitor,
            IDeviceMonitor allocationMonitor) {
        throwIfNull(device);
        throwIfNull(stateMonitor);
        mIDevice = device;
        mStateMonitor = stateMonitor;
        mAllocationMonitor = allocationMonitor;
        // Keep a short timeout to expire key in case of large state changes
        // such as flashing
        mPropertiesCache =
                CacheBuilder.newBuilder()
                        .maximumSize(50)
                        .expireAfterAccess(2, TimeUnit.MINUTES)
                        .build(
                                new CacheLoader<String, String>() {
                                    @Override
                                    public String load(String key) {
                                        throw new IllegalStateException("Should never be called");
                                    }
                                });
    }

    /** Get the {@link RunUtil} instance to use. */
    @VisibleForTesting
    protected IRunUtil getRunUtil() {
        return RunUtil.getDefault();
    }

    protected IRunUtil createRunUtil() {
        return new RunUtil();
    }

    /** Set the Clock instance to use. */
    @VisibleForTesting
    protected void setClock(Clock clock) {
        mClock = clock;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setOptions(TestDeviceOptions options) {
        throwIfNull(options);
        mOptions = options;
        if (mOptions.getFastbootBinary() != null) {
            // Setup fastboot- if it's zipped, unzip it
            // TODO: Dedup the logic with DeviceManager
            if (".zip".equals(FileUtil.getExtension(mOptions.getFastbootBinary().getName()))) {
                // Unzip the fastboot files
                try {
                    mUnpackedFastbootDir =
                            ZipUtil2.extractZipToTemp(
                                    mOptions.getFastbootBinary(), "unpacked-fastboot");
                    File unpackedFastboot = FileUtil.findFile(mUnpackedFastbootDir, "fastboot");
                    if (unpackedFastboot == null) {
                        throw new HarnessRuntimeException(
                                String.format(
                                        "device-fastboot-binary was set, but didn't contain a"
                                                + " fastboot binary."),
                                InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR);
                    }
                    setFastbootPath(unpackedFastboot.getAbsolutePath());
                } catch (IOException e) {
                    CLog.e("Failed to unpacked zipped fastboot.");
                    CLog.e(e);
                    FileUtil.recursiveDelete(mUnpackedFastbootDir);
                    mUnpackedFastbootDir = null;
                }
            } else {
                setFastbootPath(mOptions.getFastbootBinary().getAbsolutePath());
            }
        }
        mStateMonitor.setDefaultOnlineTimeout(options.getOnlineTimeout());
        mStateMonitor.setDefaultAvailableTimeout(options.getAvailableTimeout());
    }

    /**
     * Sets the max size of a tmp logcat file.
     *
     * @param size max byte size of tmp file
     */
    void setTmpLogcatSize(long size) {
        mOptions.setMaxLogcatDataSize(size);
    }

    /**
     * Sets the time in ms to wait before starting logcat capture for a online device.
     *
     * @param delay the delay in ms
     */
    public void setLogStartDelay(int delay) {
        mLogStartDelay = delay;
    }

    /** {@inheritDoc} */
    @Override
    public void setConfiguration(IConfiguration configuration) {
        mConfiguration = configuration;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IDevice getIDevice() {
        synchronized (mIDevice) {
            return mIDevice;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setIDevice(IDevice newDevice) {
        throwIfNull(newDevice);
        IDevice currentDevice = mIDevice;
        if (!getIDevice().equals(newDevice)) {
            synchronized (currentDevice) {
                mIDevice = newDevice;
            }
            mStateMonitor.setIDevice(mIDevice);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSerialNumber() {
        return getIDevice().getSerialNumber();
    }

    /**
     * Fetch a device property, from the ddmlib cache by default, and falling back to either `adb
     * shell getprop` or `fastboot getvar` depending on whether the device is in Fastboot or not.
     *
     * @param propName The name of the device property as returned by `adb shell getprop`
     * @param fastbootVar The name of the equivalent fastboot variable to query. if {@code null},
     *     fastboot query will not be attempted
     * @param description A simple description of the variable. First letter should be capitalized.
     * @return A string, possibly {@code null} or empty, containing the value of the given property
     */
    protected String internalGetProperty(String propName, String fastbootVar, String description)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        if (isStateBootloaderOrFastbootd() && fastbootVar != null) {
            CLog.i("Device %s is in fastboot mode, re-querying with '%s' for %s", getSerialNumber(),
                   fastbootVar, description);
            return getFastbootVariable(fastbootVar);
        }
        String propValue = getProperty(propName);
        if (propValue != null) {
            return propValue;
        } else {
            CLog.d(
                    "property collection '%s' for device %s is null.",
                    description, getSerialNumber());
            return null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getProperty(final String name) throws DeviceNotAvailableException {
        return getPropertyWithRecovery(name, false);
    }

    /** Version of getProperty that allows to check device status and trigger recovery if needed. */
    private String getPropertyWithRecovery(final String name, boolean recovery)
            throws DeviceNotAvailableException {
        if (getIDevice() instanceof StubDevice) {
            return null;
        }
        String property = mPropertiesCache.getIfPresent(name);
        if (property != null) {
            CLog.d("Using property %s=%s from cache.", name, property);
            return property;
        }
        try (CloseableTraceScope getProp = new CloseableTraceScope("get_property:" + name)) {
            TestDeviceState state = getDeviceState();
            if (!TestDeviceState.ONLINE.equals(state) && !TestDeviceState.RECOVERY.equals(state)) {
                if (recovery) {
                    // Only query property for online device so trigger recovery before getting
                    // property.
                    recoverDevice();
                } else {
                    if (mStateMonitor.waitForDeviceOnline() == null) {
                        CLog.w(
                                "Waited for device %s to be online but it is in state '%s', cannot "
                                        + "get property %s.",
                                getSerialNumber(), getDeviceState(), name);
                        CLog.w(
                                new RuntimeException(
                                        "This is not an actual exception but to help"
                                                + " debugging. If this happens deterministically, "
                                                + " it means the caller has wrong assumption of "
                                                + " device state and is wasting time in waiting."));
                        return null;
                    }
                }
            }
            String cmd = String.format("getprop %s", name);
            CommandResult result =
                    executeShellV2Command(cmd, PROPERTY_GET_TIMEOUT, TimeUnit.MILLISECONDS, 0);
            if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
                CLog.e(
                        "Failed to run '%s' returning null. stdout: %s\nstderr: %s\nexit code: %s",
                        cmd, result.getStdout(), result.getStderr(), result.getExitCode());
                if (result.getStderr().contains("device offline")) {
                    if (recovery) {
                        recoverDevice();
                        return getPropertyWithRecovery(name, false);
                    }
                    throw new DeviceNotAvailableException(
                            String.format("Device went offline when querying property: %s", name),
                            getSerialNumber(),
                            DeviceErrorIdentifier.DEVICE_UNAVAILABLE);
                }
                return null;
            }
            if (result.getStdout() == null || result.getStdout().trim().isEmpty()) {
                return null;
            }
            property = result.getStdout().trim();
            if (property != null) {
                if (!NEVER_CACHE_PROPERTIES.stream().anyMatch(p -> name.startsWith(p))) {
                    // Manage the cache manually to maintain exception handling
                    mPropertiesCache.put(name, property);
                }
            }
            return property;
        }
    }

    /**
     * Micro optimization (about 400 millis) by prefetching all props we need rather than call 'adb
     * getprop' for each one. i.e. It is just as fast to fetch all properties as it is to fetch one.
     * Things like device.getApiLevel(), checkApiLevelAgainstNextRelease and getBuildAlias all call
     * `adb getprop` under the hood. We fetch them in one call and call NativeDevice.setProperty.
     * Even if we don't do this, NativeDevice will itself call setProperty and cache the result for
     * future calls. We are just doing it slightly earlier. If the device is in recovery or there
     * are other errors fetching the props, we just ignore them.
     */
    public void batchPrefetchStartupBuildProps() {
        String cmd = "getprop";
        try (CloseableTraceScope ignored = new CloseableTraceScope("batchPrefetchProp")) {
            // Skip refetching if we already have the props by counting the ones in the cache
            // that we need to fetch.
            int propsAlreadyPresent = 0;
            for (String propName : propsToPrefetch) {
                if (mPropertiesCache.getIfPresent(propName) != null) {
                    propsAlreadyPresent++;
                } else {
                    break;
                }
            }
            if (propsAlreadyPresent == propsToPrefetch.size()) {
                return;
            }

            try {
                CommandResult result =
                        executeShellV2Command(cmd, PROPERTY_GET_TIMEOUT, TimeUnit.MILLISECONDS, 0);
                if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
                    CLog.w(
                            "Failed to run '%s' returning null. stdout: %s\n"
                                    + "stderr: %s\n"
                                    + "exit code: %s",
                            cmd, result.getStdout(), result.getStderr(), result.getExitCode());
                    if (result.getStdout() == null || result.getStdout().trim().isEmpty()) {
                        return;
                    }
                }
                for (String line : result.getStdout().split("\n")) {
                    String[] parts = line.trim().split("]: \\[");
                    if (parts.length != 2) {
                        continue;
                    }
                    String propName = parts[0].substring(1).trim();
                    String propValue = parts[1].substring(0, parts[1].length() - 1).trim();
                    if (propValue != null) {
                        if (propsToPrefetch.contains(propName)) {
                            mPropertiesCache.put(propName, propValue);
                        }
                    }
                }
            } catch (DeviceNotAvailableException e) {
                // okay to ignore, the real get property will deal with it.
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public long getIntProperty(String name, long defaultValue) throws DeviceNotAvailableException {
        String value = getProperty(name);
        if (value == null) {
            return defaultValue;
        }
        try {
            return Long.parseLong(value);
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    private static final List<String> TRUE_VALUES = Arrays.asList("1", "y", "yes", "on", "true");
    private static final List<String> FALSE_VALUES = Arrays.asList("0", "n", "no", "off", "false");

    /** {@inheritDoc} */
    @Override
    public boolean getBooleanProperty(String name, boolean defaultValue)
            throws DeviceNotAvailableException {
        String value = getProperty(name);
        if (value == null) {
            return defaultValue;
        }
        if (TRUE_VALUES.contains(value)) {
            return true;
        }
        if (FALSE_VALUES.contains(value)) {
            return false;
        }
        return defaultValue;
    }

    /** {@inheritDoc} */
    @Override
    public boolean setProperty(String propKey, String propValue)
            throws DeviceNotAvailableException {
        if (propKey == null || propValue == null) {
            throw new IllegalArgumentException("set property key or value cannot be null.");
        }
        String setPropCmd = String.format("\"setprop %s '%s'\"", propKey, propValue);
        CommandResult result = executeShellV2Command(setPropCmd);
        if (CommandStatus.SUCCESS.equals(result.getStatus())) {
            mPropertiesCache.invalidate(propKey);
            return true;
        }
        CLog.e(
                "Something went wrong went setting property %s (command: %s): %s",
                propKey, setPropCmd, result.getStderr());
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBootloaderVersion() throws UnsupportedOperationException,
            DeviceNotAvailableException {
        return internalGetProperty("ro.bootloader", "version-bootloader", "Bootloader");
    }

    @Override
    public String getBasebandVersion() throws DeviceNotAvailableException {
        return internalGetProperty("gsm.version.baseband", "version-baseband", "Baseband");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getProductType() throws DeviceNotAvailableException {
        return internalGetProductType(MAX_RETRY_ATTEMPTS);
    }

    /**
     * {@link #getProductType()}
     *
     * @param retryAttempts The number of times to try calling {@link #recoverDevice()} if the
     *        device's product type cannot be found.
     */
    private String internalGetProductType(int retryAttempts) throws DeviceNotAvailableException {
        String productType = internalGetProperty(DeviceProperties.BOARD, "product", "Product type");
        // fallback to ro.hardware for legacy devices
        if (Strings.isNullOrEmpty(productType)) {
            productType = internalGetProperty(DeviceProperties.HARDWARE, "product", "Product type");
        }

        // Things will likely break if we don't have a valid product type.  Try recovery (in case
        // the device is only partially booted for some reason), and if that doesn't help, bail.
        if (Strings.isNullOrEmpty(productType)) {
            if (retryAttempts > 0) {
                recoverDevice();
                productType = internalGetProductType(retryAttempts - 1);
            }

            if (Strings.isNullOrEmpty(productType)) {
                throw new DeviceNotAvailableException(
                        String.format(
                                "Could not determine product type for device %s.",
                                getSerialNumber()),
                        getSerialNumber(),
                        DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE);
            }
        }

        return productType.toLowerCase();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getFastbootProductType()
            throws DeviceNotAvailableException, UnsupportedOperationException {
        String prop = getFastbootVariable("product");
        if (prop != null) {
            prop = prop.toLowerCase();
        }
        return prop;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getProductVariant() throws DeviceNotAvailableException {
        String prop = internalGetProperty(DeviceProperties.VARIANT, "variant", "Product variant");
        if (prop == null) {
            prop =
                    internalGetProperty(
                            DeviceProperties.VARIANT_LEGACY_O_MR1, "variant", "Product variant");
        }
        if (prop == null) {
            prop =
                    internalGetProperty(
                            DeviceProperties.VARIANT_LEGACY_LESS_EQUAL_O,
                            "variant",
                            "Product variant");
        }
        if (prop != null) {
            prop = prop.toLowerCase();
        }
        return prop;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getFastbootProductVariant()
            throws DeviceNotAvailableException, UnsupportedOperationException {
        String prop = getFastbootVariable("variant");
        if (prop != null) {
            prop = prop.toLowerCase();
        }
        return prop;
    }

    /** {@inheritDoc} */
    @Override
    public String getFastbootVariable(String variableName)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        CommandResult result = executeFastbootCommand("getvar", variableName);
        CLog.d(
                "(getvar %s) output:\nstdout%s\nstderr:%s",
                variableName, result.getStdout(), result.getStderr());
        if (result.getStatus() == CommandStatus.SUCCESS) {
            Pattern fastbootProductPattern = Pattern.compile(variableName + ":\\s(.*)\\s");
            // fastboot is weird, and may dump the output on stderr instead of stdout
            String resultText = result.getStdout();
            if (resultText == null || resultText.length() < 1) {
                resultText = result.getStderr();
            }
            Matcher matcher = fastbootProductPattern.matcher(resultText);
            if (matcher.find()) {
                return matcher.group(1);
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildAlias() throws DeviceNotAvailableException {
        String alias = getProperty(DeviceProperties.BUILD_ALIAS);
        if (alias == null || alias.isEmpty()) {
            return getBuildId();
        }
        return alias;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildId() throws DeviceNotAvailableException {
        String bid = getProperty(DeviceProperties.BUILD_ID);
        if (bid == null) {
            CLog.w("Could not get device %s build id.", getSerialNumber());
            return IBuildInfo.UNKNOWN_BUILD_ID;
        }
        return bid;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildFlavor() throws DeviceNotAvailableException {
        String buildFlavor = getProperty(DeviceProperties.BUILD_FLAVOR);
        if (buildFlavor != null && !buildFlavor.isEmpty()) {
            return buildFlavor;
        }
        String productName = getProperty(DeviceProperties.PRODUCT);
        String buildType = getProperty(DeviceProperties.BUILD_TYPE);
        if (productName == null || buildType == null) {
            CLog.w("Could not get device %s build flavor.", getSerialNumber());
            return null;
        }
        return String.format("%s-%s", productName, buildType);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void executeShellCommand(final String command, final IShellOutputReceiver receiver)
            throws DeviceNotAvailableException {
        DeviceAction action = new DeviceAction() {
            @Override
            public boolean run() throws TimeoutException, IOException,
                    AdbCommandRejectedException, ShellCommandUnresponsiveException {
                getIDevice().executeShellCommand(command, receiver,
                        getCommandTimeout(), TimeUnit.MILLISECONDS);
                return true;
            }
        };
        performDeviceAction(String.format("shell %s", command), action, MAX_RETRY_ATTEMPTS);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void executeShellCommand(final String command, final IShellOutputReceiver receiver,
            final long maxTimeToOutputShellResponse, final TimeUnit timeUnit,
            final int retryAttempts) throws DeviceNotAvailableException {
        DeviceAction action = new DeviceAction() {
            @Override
            public boolean run() throws TimeoutException, IOException, AdbCommandRejectedException,
                    ShellCommandUnresponsiveException {
                getIDevice().executeShellCommand(command, receiver,
                        maxTimeToOutputShellResponse, timeUnit);
                return true;
            }
        };
        performDeviceAction(String.format("shell %s", command), action, retryAttempts);
    }

    /** {@inheritDoc} */
    @Override
    public void executeShellCommand(
            final String command,
            final IShellOutputReceiver receiver,
            final long maxTimeoutForCommand,
            final long maxTimeToOutputShellResponse,
            final TimeUnit timeUnit,
            final int retryAttempts)
            throws DeviceNotAvailableException {
        DeviceAction action =
                new DeviceAction() {
                    @Override
                    public boolean run()
                            throws TimeoutException, IOException, AdbCommandRejectedException,
                                    ShellCommandUnresponsiveException {
                        getIDevice()
                                .executeShellCommand(
                                        command,
                                        receiver,
                                        maxTimeoutForCommand,
                                        maxTimeToOutputShellResponse,
                                        timeUnit);
                        return true;
                    }
                };
        performDeviceAction(String.format("shell %s", command), action, retryAttempts);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String executeShellCommand(String command) throws DeviceNotAvailableException {
        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
        executeShellCommand(command, receiver);
        String output = receiver.getOutput();
        if (mExecuteShellCommandLogs != null) {
            // Log all output to a dedicated file as it can be very verbose.
            String formatted =
                    LogUtil.getLogFormatString(
                            LogLevel.VERBOSE,
                            "NativeDevice",
                            String.format(
                                    "%s on %s returned %s\n==== END OF OUTPUT ====\n",
                                    command, getSerialNumber(), output));
            try {
                FileUtil.writeToFile(formatted, mExecuteShellCommandLogs, true);
            } catch (IOException e) {
                // Ignore the full error
                CLog.e("Failed to log to executeShellCommand log: %s", e.getMessage());
            }
        }
        if (output.length() > 80) {
            CLog.v(
                    "%s on %s returned %s <truncated - See executeShellCommand log for full trace>",
                    command, getSerialNumber(), output.substring(0, 80));
        } else {
            CLog.v("%s on %s returned %s", command, getSerialNumber(), output);
        }
        return output;
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(String cmd) throws DeviceNotAvailableException {
        return executeShellV2Command(cmd, getCommandTimeout(), TimeUnit.MILLISECONDS);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(String cmd, File pipeAsInput)
            throws DeviceNotAvailableException {
        return executeShellV2Command(
                cmd,
                pipeAsInput,
                null,
                getCommandTimeout(),
                TimeUnit.MILLISECONDS,
                MAX_RETRY_ATTEMPTS);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(String cmd, OutputStream pipeToOutput)
            throws DeviceNotAvailableException {
        return executeShellV2Command(
                cmd,
                null,
                pipeToOutput,
                getCommandTimeout(),
                TimeUnit.MILLISECONDS,
                MAX_RETRY_ATTEMPTS);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(
            String cmd, final long maxTimeoutForCommand, final TimeUnit timeUnit)
            throws DeviceNotAvailableException {
        return executeShellV2Command(
                cmd, null, null, maxTimeoutForCommand, timeUnit, MAX_RETRY_ATTEMPTS);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(
            String cmd, final long maxTimeoutForCommand, final TimeUnit timeUnit, int retryAttempts)
            throws DeviceNotAvailableException {
        return executeShellV2Command(
                cmd, null, null, maxTimeoutForCommand, timeUnit, retryAttempts);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(
            String cmd,
            File pipeAsInput,
            OutputStream pipeToOutput,
            final long maxTimeoutForCommand,
            final TimeUnit timeUnit,
            int retryAttempts)
            throws DeviceNotAvailableException {
        return executeShellV2Command(
                cmd,
                pipeAsInput,
                pipeToOutput,
                /*pipeToError=*/ null,
                maxTimeoutForCommand,
                timeUnit,
                retryAttempts);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeShellV2Command(
            String cmd,
            File pipeAsInput,
            OutputStream pipeToOutput,
            OutputStream pipeToError,
            final long maxTimeoutForCommand,
            final TimeUnit timeUnit,
            int retryAttempts)
            throws DeviceNotAvailableException {
        // If the device does not support the v2 shell features. Exit status will not be propagated
        // and stdout/stderr will be merged in stdout.
        //
        // There's nothing we can do to separate the two streams, but we can alter the command to
        // retrieve the exit status.
        //
        // Note that this does *not* call `adb features` on each invocation. ddmlib caches all the
        // adb features on the first query.
        boolean parseExitStatus =
                !getIDevice().supportsFeature(IDevice.Feature.SHELL_V2)
                        && getOptions().useExitStatusWorkaround();

        final String[] fullCmd = buildAdbShellCommand(cmd, parseExitStatus);
        AdbShellAction adbActionV2 =
                new AdbShellAction(
                        fullCmd,
                        pipeAsInput,
                        pipeToOutput,
                        pipeToError,
                        timeUnit.toMillis(maxTimeoutForCommand));
        performDeviceAction(String.format("adb %s", fullCmd[4]), adbActionV2, retryAttempts);
        if (parseExitStatus) {
            postProcessExitStatus(adbActionV2.mResult);
        }
        return adbActionV2.mResult;
    }

    private void postProcessExitStatus(@Nonnull CommandResult result) {
        String stdout = result.getStdout();
        int delimiterIndex = stdout.lastIndexOf(EXIT_STATUS_DELIMITER);
        if (delimiterIndex < 0) {
            result.setStatus(CommandStatus.FAILED);
            return;
        }
        String actualStdout = stdout.substring(0, delimiterIndex);
        String exitStatusText = stdout.substring(delimiterIndex + 1);
        result.setExitCode(Integer.parseUnsignedInt(exitStatusText.trim()));
        result.setStdout(actualStdout);
        if (result.getStatus() == CommandStatus.SUCCESS && result.getExitCode() != 0) {
            result.setStatus(CommandStatus.FAILED);
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean runInstrumentationTests(
            final IRemoteAndroidTestRunner runner,
            final Collection<ITestLifeCycleReceiver> listeners)
            throws DeviceNotAvailableException {
        RunFailureListener failureListener = new RunFailureListener();
        List<ITestRunListener> runListeners = new ArrayList<>();
        runListeners.add(failureListener);
        runListeners.add(new TestRunToTestInvocationForwarder(listeners));

        if ((mConfiguration != null)
                && mConfiguration.getCoverageOptions().isCoverageEnabled()
                && mConfiguration
                        .getCoverageOptions()
                        .getCoverageToolchains()
                        .contains(Toolchain.JACOCO)) {
            runner.setCoverage(true);
        }

        DeviceAction runTestsAction =
                new DeviceAction() {
                    @Override
                    public boolean run()
                            throws IOException, TimeoutException, AdbCommandRejectedException,
                                    ShellCommandUnresponsiveException, InstallException,
                                    SyncException {
                        runner.run(runListeners);
                        return true;
                    }
                };
        boolean result = performDeviceAction(String.format("run %s instrumentation tests",
                runner.getPackageName()), runTestsAction, 0);
        if (failureListener.isRunFailure()) {
            waitForDeviceAvailable();
        }
        return result;
    }

    /** {@inheritDoc} */
    @Override
    public boolean runInstrumentationTests(
            IRemoteAndroidTestRunner runner, ITestLifeCycleReceiver... listeners)
            throws DeviceNotAvailableException {
        List<ITestLifeCycleReceiver> listenerList = new ArrayList<>();
        listenerList.addAll(Arrays.asList(listeners));
        return runInstrumentationTests(runner, listenerList);
    }

    /** {@inheritDoc} */
    @Override
    public boolean runInstrumentationTestsAsUser(
            final IRemoteAndroidTestRunner runner,
            int userId,
            final Collection<ITestLifeCycleReceiver> listeners)
            throws DeviceNotAvailableException {
        String oldRunTimeOptions = appendUserRunTimeOptionToRunner(runner, userId);
        boolean result = runInstrumentationTests(runner, listeners);
        resetUserRunTimeOptionToRunner(runner, oldRunTimeOptions);
        return result;
    }

    /** {@inheritDoc} */
    @Override
    public boolean runInstrumentationTestsAsUser(
            IRemoteAndroidTestRunner runner, int userId, ITestLifeCycleReceiver... listeners)
            throws DeviceNotAvailableException {
        String oldRunTimeOptions = appendUserRunTimeOptionToRunner(runner, userId);
        boolean result = runInstrumentationTests(runner, listeners);
        resetUserRunTimeOptionToRunner(runner, oldRunTimeOptions);
        return result;
    }

    /**
     * Helper method to add user run time option to {@link RemoteAndroidTestRunner}
     *
     * @param runner {@link IRemoteAndroidTestRunner}
     * @param userId the integer of the user id to run as.
     * @return original run time options.
     */
    private String appendUserRunTimeOptionToRunner(final IRemoteAndroidTestRunner runner, int userId) {
        if (runner instanceof RemoteAndroidTestRunner) {
            String original = ((RemoteAndroidTestRunner) runner).getRunOptions();
            String userRunTimeOption = String.format("--user %s", Integer.toString(userId));
            String updated = (original != null) ? (original + " " + userRunTimeOption)
                    : userRunTimeOption;
            ((RemoteAndroidTestRunner) runner).setRunOptions(updated);
            return original;
        } else {
            throw new IllegalStateException(String.format("%s runner does not support multi-user",
                    runner.getClass().getName()));
        }
    }

    /**
     * Helper method to reset the run time options to {@link RemoteAndroidTestRunner}
     *
     * @param runner {@link IRemoteAndroidTestRunner}
     * @param oldRunTimeOptions
     */
    private void resetUserRunTimeOptionToRunner(final IRemoteAndroidTestRunner runner,
            String oldRunTimeOptions) {
        if (runner instanceof RemoteAndroidTestRunner) {
            if (oldRunTimeOptions != null) {
                ((RemoteAndroidTestRunner) runner).setRunOptions(oldRunTimeOptions);
            }
        } else {
            throw new IllegalStateException(String.format("%s runner does not support multi-user",
                    runner.getClass().getName()));
        }
    }

    private static class RunFailureListener extends StubTestRunListener {
        private boolean mIsRunFailure = false;

        @Override
        public void testRunFailed(String message) {
            mIsRunFailure = true;
        }

        public boolean isRunFailure() {
            return mIsRunFailure;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRuntimePermissionSupported() throws DeviceNotAvailableException {
        int apiLevel = getApiLevel();
        boolean condition = apiLevel > 22;
        if (!condition) {
            CLog.w(
                    "isRuntimePermissionSupported requires api level above 22, device reported "
                            + "'%s'",
                    apiLevel);
        }
        return condition;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAppEnumerationSupported() throws DeviceNotAvailableException {
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isBypassLowTargetSdkBlockSupported() throws DeviceNotAvailableException {
        return checkApiLevelAgainstNextRelease(34);
    }

    /**
     * helper method to throw exception if runtime permission isn't supported
     * @throws DeviceNotAvailableException
     */
    protected void ensureRuntimePermissionSupported() throws DeviceNotAvailableException {
        boolean runtimePermissionSupported = isRuntimePermissionSupported();
        if (!runtimePermissionSupported) {
            throw new UnsupportedOperationException(
                    "platform on device does not support runtime permission granting!");
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackage(final File packageFile, final boolean reinstall,
            final String... extraArgs) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackage(File packageFile, boolean reinstall, boolean grantPermissions,
            String... extraArgs) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackageForUser(File packageFile, boolean reinstall, int userId,
            String... extraArgs) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String installPackageForUser(File packageFile, boolean reinstall,
            boolean grantPermissions, int userId, String... extraArgs)
                    throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String uninstallPackage(final String packageName) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /** {@inheritDoc} */
    @Override
    public String uninstallPackageForUser(final String packageName, int userId)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package Manager's features");
    }

    /** {@inheritDoc} */
    @Override
    public boolean pullFile(final String remoteFilePath, final File localFile, int userId)
            throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.PULL_FILE_COUNT, 1);

        try {
            if (isSdcardOrEmulated(remoteFilePath) && userId != 0) {
                ContentProviderHandler handler = getContentProvider();
                if (handler != null) {
                    return handler.pullFile(remoteFilePath, localFile);
                }
            }
            return pullFileInternal(remoteFilePath, localFile);
        } finally {
            long totalTime = System.currentTimeMillis() - startTime;
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.PULL_FILE_TIME, totalTime);
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean pullFile(final String remoteFilePath, final File localFile)
            throws DeviceNotAvailableException {
        return pullFile(remoteFilePath, localFile, getCurrentUserCompatible());
    }

    /** {@inheritDoc} */
    @Override
    public File pullFile(String remoteFilePath, int userId) throws DeviceNotAvailableException {
        File localFile = null;
        boolean success = false;
        try {
            localFile = FileUtil.createTempFileForRemote(remoteFilePath, null);
            if (pullFile(remoteFilePath, localFile, userId)) {
                success = true;
                return localFile;
            }
        } catch (IOException e) {
            CLog.w("Encountered IOException while trying to pull '%s':", remoteFilePath);
            CLog.e(e);
        } finally {
            if (!success) {
                FileUtil.deleteFile(localFile);
            }
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public File pullFile(String remoteFilePath) throws DeviceNotAvailableException {
        return pullFile(remoteFilePath, getCurrentUserCompatible());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String pullFileContents(String remoteFilePath) throws DeviceNotAvailableException {
        File temp = pullFile(remoteFilePath);

        if (temp != null) {
            try {
                return FileUtil.readStringFromFile(temp);
            } catch (IOException e) {
                CLog.e(String.format("Could not pull file: %s", remoteFilePath));
            } finally {
                FileUtil.deleteFile(temp);
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public File pullFileFromExternal(String remoteFilePath) throws DeviceNotAvailableException {
        String externalPath = getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
        String fullPath = new File(externalPath, remoteFilePath).getPath();
        return pullFile(fullPath);
    }

    protected boolean pullFileInternal(String remoteFilePath, File localFile)
            throws DeviceNotAvailableException {
        DeviceAction pullAction =
                new DeviceAction() {
                    @Override
                    public boolean run()
                            throws TimeoutException, IOException, AdbCommandRejectedException,
                                    SyncException {
                        SyncService syncService = null;
                        boolean status = false;
                        try {
                            syncService = getIDevice().getSyncService();
                            syncService.pullFile(
                                    interpolatePathVariables(remoteFilePath),
                                    localFile.getAbsolutePath(),
                                    SyncService.getNullProgressMonitor());
                            status = true;
                        } catch (SyncException e) {
                            CLog.w(
                                    "Failed to pull %s from %s to %s. Message %s",
                                    remoteFilePath,
                                    getSerialNumber(),
                                    localFile.getAbsolutePath(),
                                    e.getMessage());
                            throw e;
                        } finally {
                            if (syncService != null) {
                                syncService.close();
                            }
                        }
                        return status;
                    }
                };
        return performDeviceAction(
                String.format("pull %s to %s", remoteFilePath, localFile.getAbsolutePath()),
                pullAction,
                MAX_RETRY_ATTEMPTS);
    }

    /**
     * Helper function that watches for the string "${EXTERNAL_STORAGE}" and replaces it with the
     * pathname of the EXTERNAL_STORAGE mountpoint.  Specifically intended to be used for pathnames
     * that are being passed to SyncService, which does not support variables inside of filenames.
     */
    String interpolatePathVariables(String path) {
        final String esString = "${EXTERNAL_STORAGE}";
        if (path.contains(esString)) {
            final String esPath = getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
            path = path.replace(esString, esPath);
        }
        return path;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean pushFile(final File localFile, final String remoteFilePath)
            throws DeviceNotAvailableException {
        return pushFileInternal(localFile, remoteFilePath, false);
    }

    @Override
    public boolean pushFile(
            final File localFile,
            final String remoteFilePath,
            boolean evaluateContentProviderNeeded)
            throws DeviceNotAvailableException {
        boolean skipContentProvider = false;
        if (evaluateContentProviderNeeded) {
            skipContentProvider = getCurrentUserCompatible() == 0;
        }
        return pushFileInternal(localFile, remoteFilePath, skipContentProvider);
    }

    @VisibleForTesting
    boolean pushFileInternal(final File localFile, final String remoteFilePath,
            boolean skipContentProvider) throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.PUSH_FILE_COUNT, 1);
        try {
            if (!skipContentProvider) {
                if (isSdcardOrEmulated(remoteFilePath)) {
                    ContentProviderHandler handler = getContentProvider();
                    if (handler != null) {
                        return handler.pushFile(localFile, remoteFilePath);
                    }
                }
            }

            DeviceAction pushAction =
                    new DeviceAction() {
                        @Override
                        public boolean run()
                                throws TimeoutException, IOException, AdbCommandRejectedException,
                                        SyncException {
                            SyncService syncService = null;
                            boolean status = false;
                            try {
                                syncService = getIDevice().getSyncService();
                                if (syncService == null) {
                                    throw new IOException("SyncService returned null.");
                                }
                                syncService.pushFile(
                                        localFile.getAbsolutePath(),
                                        interpolatePathVariables(remoteFilePath),
                                        SyncService.getNullProgressMonitor());
                                status = true;
                            } catch (SyncException e) {
                                CLog.w(
                                        "Failed to push %s to %s on device %s. Message: '%s'. "
                                                + "Error code: %s",
                                        localFile.getAbsolutePath(),
                                        remoteFilePath,
                                        getSerialNumber(),
                                        e.getMessage(),
                                        e.getErrorCode());
                                // TODO: check if ddmlib can report a better error
                                if (SyncError.TRANSFER_PROTOCOL_ERROR.equals(e.getErrorCode())) {
                                    if (e.getMessage().contains("Permission denied")) {
                                        return false;
                                    }
                                }
                                throw e;
                            } finally {
                                if (syncService != null) {
                                    syncService.close();
                                }
                            }
                            return status;
                        }
                    };
            return performDeviceAction(
                    String.format("push %s to %s", localFile.getAbsolutePath(), remoteFilePath),
                    pushAction,
                    MAX_RETRY_ATTEMPTS);
        } finally {
            long totalTime = System.currentTimeMillis() - startTime;
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.PUSH_FILE_TIME, totalTime);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean pushString(final String contents, final String remoteFilePath)
            throws DeviceNotAvailableException {
        File tmpFile = null;
        try {
            tmpFile = FileUtil.createTempFile("temp", ".txt");
            FileUtil.writeToFile(contents, tmpFile);
            return pushFile(tmpFile, remoteFilePath);
        } catch (IOException e) {
            CLog.e(e);
            return false;
        } finally {
            FileUtil.deleteFile(tmpFile);
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean doesFileExist(String deviceFilePath) throws DeviceNotAvailableException {
        return doesFileExist(deviceFilePath, getCurrentUserCompatible());
    }

    @Override
    public boolean doesFileExist(String deviceFilePath, int userId)
            throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        try {
            // Skip ContentProvider for user 0
            if (isSdcardOrEmulated(deviceFilePath) && userId != 0) {
                ContentProviderHandler handler = getContentProvider();
                if (handler != null) {
                    CLog.d("Delegating check to ContentProvider doesFileExist(%s)", deviceFilePath);
                    return handler.doesFileExist(deviceFilePath);
                }
            }
            CLog.d("Using 'ls' to check doesFileExist(%s)", deviceFilePath);
            String lsGrep = executeShellCommand(String.format("ls \"%s\"", deviceFilePath));
            return !lsGrep.contains("No such file or directory");
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.DOES_FILE_EXISTS_TIME,
                    System.currentTimeMillis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.DOES_FILE_EXISTS_COUNT, 1);
        }
    }

    @Override
    public void registerDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver) {
        mDeviceActionReceivers.add(deviceActionReceiver);
    }

    @Override
    public void deregisterDeviceActionReceiver(IDeviceActionReceiver deviceActionReceiver) {
        mDeviceActionReceivers.remove(deviceActionReceiver);
    }

    /** {@inheritDoc} */
    @Override
    public void deleteFile(String deviceFilePath) throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        try {
            if (isSdcardOrEmulated(deviceFilePath)) {
                int currentUser = getCurrentUserCompatible();
                if (currentUser != 0) {
                    ContentProviderHandler handler = getContentProvider();
                    if (handler != null) {
                        if (handler.deleteFile(deviceFilePath)) {
                            return;
                        }
                    }
                }
            }
            // Fallback to the direct command if content provider is unsuccessful
            String path = StringEscapeUtils.escapeShell(deviceFilePath);
            // Escape spaces to handle filename with spaces
            path = path.replaceAll(" ", "\\ ");
            executeShellCommand(String.format("rm -rf %s", StringEscapeUtils.escapeShell(path)));
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.DELETE_DEVICE_FILE_TIME,
                    System.currentTimeMillis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.DELETE_DEVICE_FILE_COUNT, 1);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long getExternalStoreFreeSpace() throws DeviceNotAvailableException {
        String externalStorePath = getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
        return getPartitionFreeSpace(externalStorePath);
    }

    /** {@inheritDoc} */
    @Override
    public long getPartitionFreeSpace(String partition) throws DeviceNotAvailableException {
        CLog.i("Checking free space for %s on partition %s", getSerialNumber(), partition);
        String output = getDfOutput(partition);
        // Try coreutils/toybox style output first.
        Long available = parseFreeSpaceFromModernOutput(output);
        if (available != null) {
            return available;
        }
        // Then the two legacy toolbox formats.
        available = parseFreeSpaceFromAvailable(output);
        if (available != null) {
            return available;
        }
        available = parseFreeSpaceFromFree(partition, output);
        if (available != null) {
            return available;
        }

        CLog.e("free space command output \"%s\" did not match expected patterns", output);
        return 0;
    }

    /**
     * Run the 'df' shell command and return output, making multiple attempts if necessary.
     *
     * @param externalStorePath the path to check
     * @return the output from 'shell df path'
     * @throws DeviceNotAvailableException
     */
    private String getDfOutput(String externalStorePath) throws DeviceNotAvailableException {
        for (int i=0; i < MAX_RETRY_ATTEMPTS; i++) {
            String output = executeShellCommand(String.format("df %s", externalStorePath));
            if (output.trim().length() > 0) {
                return output;
            }
        }
        throw new DeviceUnresponsiveException(String.format(
                "Device %s not returning output from df command after %d attempts",
                getSerialNumber(), MAX_RETRY_ATTEMPTS), getSerialNumber());
    }

    /**
     * Parses a partition's available space from the legacy output of a 'df' command, used
     * pre-gingerbread.
     * <p/>
     * Assumes output format of:
     * <br>/
     * <code>
     * [partition]: 15659168K total, 51584K used, 15607584K available (block size 32768)
     * </code>
     * @param dfOutput the output of df command to parse
     * @return the available space in kilobytes or <code>null</code> if output could not be parsed
     */
    private Long parseFreeSpaceFromAvailable(String dfOutput) {
        final Pattern freeSpacePattern = Pattern.compile("(\\d+)K available");
        Matcher patternMatcher = freeSpacePattern.matcher(dfOutput);
        if (patternMatcher.find()) {
            String freeSpaceString = patternMatcher.group(1);
            try {
                return Long.parseLong(freeSpaceString);
            } catch (NumberFormatException e) {
                // fall through
            }
        }
        return null;
    }

    /**
     * Parses a partition's available space from the 'table-formatted' output of a toolbox 'df'
     * command, used from gingerbread to lollipop.
     * <p/>
     * Assumes output format of:
     * <br/>
     * <code>
     * Filesystem             Size   Used   Free   Blksize
     * <br/>
     * [partition]:              3G   790M  2G     4096
     * </code>
     * @param dfOutput the output of df command to parse
     * @return the available space in kilobytes or <code>null</code> if output could not be parsed
     */
    Long parseFreeSpaceFromFree(String externalStorePath, String dfOutput) {
        Long freeSpace = null;
        final Pattern freeSpaceTablePattern = Pattern.compile(String.format(
                //fs   Size         Used         Free
                "%s\\s+[\\w\\d\\.]+\\s+[\\w\\d\\.]+\\s+([\\d\\.]+)(\\w)", externalStorePath));
        Matcher tablePatternMatcher = freeSpaceTablePattern.matcher(dfOutput);
        if (tablePatternMatcher.find()) {
            String numericValueString = tablePatternMatcher.group(1);
            String unitType = tablePatternMatcher.group(2);
            try {
                float freeSpaceFloat = Float.parseFloat(numericValueString);
                if (unitType.equals("M")) {
                    freeSpaceFloat = freeSpaceFloat * 1024;
                } else if (unitType.equals("G")) {
                    freeSpaceFloat = freeSpaceFloat * 1024 * 1024;
                }
                freeSpace = (long) freeSpaceFloat;
            } catch (NumberFormatException e) {
                // fall through
            }
        }
        return freeSpace;
    }

    /**
     * Parses a partition's available space from the modern coreutils/toybox 'df' output, used
     * after lollipop.
     * <p/>
     * Assumes output format of:
     * <br/>
     * <code>
     * Filesystem      1K-blocks	Used  Available Use% Mounted on
     * <br/>
     * /dev/fuse        11585536    1316348   10269188  12% /mnt/shell/emulated
     * </code>
     * @param dfOutput the output of df command to parse
     * @return the available space in kilobytes or <code>null</code> if output could not be parsed
     */
    Long parseFreeSpaceFromModernOutput(String dfOutput) {
        Matcher matcher = DF_PATTERN.matcher(dfOutput);
        if (matcher.find()) {
            try {
                return Long.parseLong(matcher.group(2));
            } catch (NumberFormatException e) {
                // fall through
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getMountPoint(String mountName) {
        try {
            return mStateMonitor.getMountPoint(mountName);
        } catch (DeviceNotAvailableException e) {
            CLog.e(e);
            return null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<MountPointInfo> getMountPointInfo() throws DeviceNotAvailableException {
        final String mountInfo = executeShellCommand("cat /proc/mounts");
        final String[] mountInfoLines = mountInfo.split("\r?\n");
        List<MountPointInfo> list = new ArrayList<>(mountInfoLines.length);

        for (String line : mountInfoLines) {
            // We ignore the last two fields
            // /dev/block/mtdblock4 /cache yaffs2 rw,nosuid,nodev,relatime 0 0
            final String[] parts = line.split("\\s+", 5);
            list.add(new MountPointInfo(parts[0], parts[1], parts[2], parts[3]));
        }

        return list;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public MountPointInfo getMountPointInfo(String mountpoint) throws DeviceNotAvailableException {
        // The overhead of parsing all of the lines should be minimal
        List<MountPointInfo> mountpoints = getMountPointInfo();
        for (MountPointInfo info : mountpoints) {
            if (mountpoint.equals(info.mountpoint)) {
                return info;
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public IFileEntry getFileEntry(String path) throws DeviceNotAvailableException {
        path = interpolatePathVariables(path);
        String[] pathComponents = path.split(FileListingService.FILE_SEPARATOR);
        FileListingService service = getFileListingService();
        IFileEntry rootFile = new FileEntryWrapper(this, service.getRoot());
        return FileEntryWrapper.getDescendant(rootFile, Arrays.asList(pathComponents));
    }

    /**
     * Unofficial helper to get a {@link FileEntry} from a non-root path. FIXME: Refactor the
     * FileEntry system to have it available from any path. (even non root).
     *
     * @param entry a {@link FileEntry} not necessarily root as Ddmlib requires.
     * @return a {@link FileEntryWrapper} representing the FileEntry.
     * @throws DeviceNotAvailableException
     */
    public IFileEntry getFileEntry(FileEntry entry) throws DeviceNotAvailableException {
        // FileEntryWrapper is going to construct the list of child file internally.
        return new FileEntryWrapper(this, entry);
    }

    /** {@inheritDoc} */
    @Override
    public boolean isExecutable(String fullPath) throws DeviceNotAvailableException {
        String fileMode = executeShellCommand(String.format("ls -l %s", fullPath));
        if (fileMode != null) {
            return EXE_FILE.matcher(fileMode).find();
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isDirectory(String path) throws DeviceNotAvailableException {
        return executeShellCommand(String.format("ls -ld %s", path)).charAt(0) == 'd';
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String[] getChildren(String path) throws DeviceNotAvailableException {
        String lsOutput = executeShellCommand(String.format("ls -A1 %s", path));
        if (lsOutput.trim().isEmpty()) {
            return new String[0];
        }
        return lsOutput.split("\r?\n");
    }

    /**
     * Retrieve the {@link FileListingService} for the {@link IDevice}, making multiple attempts
     * and recovery operations if necessary.
     * <p/>
     * This is necessary because {@link IDevice#getFileListingService()} can return
     * <code>null</code> if device is in fastboot.  The symptom of this condition is that the
     * current {@link #getIDevice()} is a {@link StubDevice}.
     *
     * @return the {@link FileListingService}
     * @throws DeviceNotAvailableException if device communication is lost.
     */
    private FileListingService getFileListingService() throws DeviceNotAvailableException  {
        final FileListingService[] service = new FileListingService[1];
        DeviceAction serviceAction = new DeviceAction() {
            @Override
            public boolean run() throws IOException, TimeoutException, AdbCommandRejectedException,
                    ShellCommandUnresponsiveException, InstallException, SyncException {
                service[0] = getIDevice().getFileListingService();
                if (service[0] == null) {
                    // could not get file listing service - must be a stub device - enter recovery
                    throw new IOException("Could not get file listing service");
                }
                return true;
            }
        };
        performDeviceAction("getFileListingService", serviceAction, MAX_RETRY_ATTEMPTS);
        return service[0];
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean pushDir(File localFileDir, String deviceFilePath)
            throws DeviceNotAvailableException {
        return pushDir(localFileDir, deviceFilePath, new HashSet<>());
    }

    /** {@inheritDoc} */
    @Override
    public boolean pushDir(
            File localFileDir, String deviceFilePath, Set<String> excludedDirectories)
            throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        try {
            if (isSdcardOrEmulated(deviceFilePath)) {
                Integer currentUser = getCurrentUserCompatible();
                if (currentUser != 0) {
                    ContentProviderHandler handler = getContentProvider();
                    if (handler != null) {
                        return handler.pushDir(localFileDir, deviceFilePath, excludedDirectories);
                    }
                } else {
                    // Remove the special handling when content provider performance is better
                    CLog.d("Push without content provider for user '%s'", currentUser);
                }
            }
            return pushDirInternal(localFileDir, deviceFilePath, excludedDirectories);
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.PUSH_DIR_TIME, System.currentTimeMillis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.PUSH_DIR_COUNT, 1);
        }
    }

    private boolean pushDirInternal(
            File localFileDir, String deviceFilePath, Set<String> excludedDirectories)
            throws DeviceNotAvailableException {
        if (!localFileDir.isDirectory()) {
            CLog.e("file %s is not a directory", localFileDir.getAbsolutePath());
            return false;
        }
        File[] childFiles = localFileDir.listFiles();
        if (childFiles == null) {
            CLog.e("Could not read files in %s", localFileDir.getAbsolutePath());
            return false;
        }
        for (File childFile : childFiles) {
            String remotePath = String.format("%s/%s", deviceFilePath, childFile.getName());
            if (childFile.isDirectory()) {
                // If we encounter a filtered directory do not push it.
                if (excludedDirectories.contains(childFile.getName())) {
                    CLog.d(
                            "%s directory was not pushed because it was filtered.",
                            childFile.getAbsolutePath());
                    continue;
                }
                executeShellCommand(String.format("mkdir -p \"%s\"", remotePath));
                if (!pushDirInternal(childFile, remotePath, excludedDirectories)) {
                    return false;
                }
            } else if (childFile.isFile()) {
                if (!pushFileInternal(childFile, remotePath, true)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean pullDir(String deviceFilePath, File localDir)
            throws DeviceNotAvailableException {
        long startTime = System.currentTimeMillis();
        try {
            int currentUser = getCurrentUserCompatible();
            if (isSdcardOrEmulated(deviceFilePath)) {
                if (currentUser != 0) {
                    ContentProviderHandler handler = getContentProvider();
                    if (handler != null) {
                        return handler.pullDir(deviceFilePath, localDir);
                    }
                }
            }

            return pullDirInternal(deviceFilePath, localDir, currentUser);
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.PULL_DIR_TIME, System.currentTimeMillis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.PULL_DIR_COUNT, 1);
        }
    }

    private boolean pullDirInternal(String deviceFilePath, File localDir, int userId)
            throws DeviceNotAvailableException {
        if (!localDir.isDirectory()) {
            CLog.e("Local path %s is not a directory", localDir.getAbsolutePath());
            return false;
        }
        if (!doesFileExist(deviceFilePath, userId)) {
            CLog.e("Device path %s does not exist to be pulled.", deviceFilePath);
            return false;
        }
        if (!isDirectory(deviceFilePath)) {
            CLog.e("Device path %s is not a directory", deviceFilePath);
            return false;
        }
        FileEntry entryRoot =
                new FileEntry(null, deviceFilePath, FileListingService.TYPE_DIRECTORY, false);
        IFileEntry entry = getFileEntry(entryRoot);
        Collection<IFileEntry> children = entry.getChildren(false);
        if (children.isEmpty()) {
            CLog.i("Device path is empty, nothing to do.");
            return true;
        }
        for (IFileEntry item : children) {
            if (item.isDirectory()) {
                // handle sub dir
                File subDir = new File(localDir, item.getName());
                if (!subDir.mkdir()) {
                    CLog.w(
                            "Failed to create sub directory %s, aborting.",
                            subDir.getAbsolutePath());
                    return false;
                }
                String deviceSubDir = item.getFullPath();
                if (!pullDirInternal(deviceSubDir, subDir, userId)) {
                    CLog.w("Failed to pull sub directory %s from device, aborting", deviceSubDir);
                    return false;
                }
            } else {
                // handle regular file
                File localFile = new File(localDir, item.getName());
                String fullPath = item.getFullPath();
                if (!pullFileInternal(fullPath, localFile)) {
                    CLog.w("Failed to pull file %s from device, aborting", fullPath);
                    return false;
                }
            }
        }
        return true;
    }

    /** Checks whether path is external storage path. */
    private boolean isSdcardOrEmulated(String path) {
        return path.startsWith(SD_CARD) || path.startsWith(STORAGE_EMULATED);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean syncFiles(File localFileDir, String deviceFilePath)
            throws DeviceNotAvailableException {
        if (localFileDir == null || deviceFilePath == null) {
            throw new IllegalArgumentException("syncFiles does not take null arguments");
        }
        CLog.i("Syncing %s to %s on device %s",
                localFileDir.getAbsolutePath(), deviceFilePath, getSerialNumber());
        if (!localFileDir.isDirectory()) {
            CLog.e("file %s is not a directory", localFileDir.getAbsolutePath());
            return false;
        }
        // get the real destination path. This is done because underlying syncService.push
        // implementation will add localFileDir.getName() to destination path
        deviceFilePath = String.format("%s/%s", interpolatePathVariables(deviceFilePath),
                localFileDir.getName());
        if (!doesFileExist(deviceFilePath)) {
            executeShellCommand(String.format("mkdir -p \"%s\"", deviceFilePath));
        }
        IFileEntry remoteFileEntry = getFileEntry(deviceFilePath);
        if (remoteFileEntry == null) {
            CLog.e("Could not find remote file entry %s ", deviceFilePath);
            return false;
        }

        return syncFiles(localFileDir, remoteFileEntry);
    }

    /**
     * Recursively sync newer files.
     *
     * @param localFileDir the local {@link File} directory to sync
     * @param remoteFileEntry the remote destination {@link IFileEntry}
     * @return <code>true</code> if files were synced successfully
     * @throws DeviceNotAvailableException
     */
    private boolean syncFiles(File localFileDir, final IFileEntry remoteFileEntry)
            throws DeviceNotAvailableException {
        CLog.d("Syncing %s to %s on %s", localFileDir.getAbsolutePath(),
                remoteFileEntry.getFullPath(), getSerialNumber());
        // find newer files to sync
        File[] localFiles = localFileDir.listFiles(new NoHiddenFilesFilter());
        ArrayList<String> filePathsToSync = new ArrayList<>();
        for (File localFile : localFiles) {
            IFileEntry entry = remoteFileEntry.findChild(localFile.getName());
            if (entry == null) {
                CLog.d("Detected missing file path %s", localFile.getAbsolutePath());
                filePathsToSync.add(localFile.getAbsolutePath());
            } else if (localFile.isDirectory()) {
                // This directory exists remotely. recursively sync it to sync only its newer files
                // contents
                if (!syncFiles(localFile, entry)) {
                    return false;
                }
            } else if (isNewer(localFile, entry)) {
                CLog.d("Detected newer file %s", localFile.getAbsolutePath());
                filePathsToSync.add(localFile.getAbsolutePath());
            }
        }

        if (filePathsToSync.size() == 0) {
            CLog.d("No files to sync");
            return true;
        }
        final String files[] = filePathsToSync.toArray(new String[filePathsToSync.size()]);
        DeviceAction syncAction = new DeviceAction() {
            @Override
            public boolean run() throws TimeoutException, IOException, AdbCommandRejectedException,
                    SyncException {
                SyncService syncService = null;
                boolean status = false;
                try {
                    syncService = getIDevice().getSyncService();
                    syncService.push(files, remoteFileEntry.getFileEntry(),
                            SyncService.getNullProgressMonitor());
                    status = true;
                } catch (SyncException e) {
                    CLog.w("Failed to sync files to %s on device %s. Message %s",
                            remoteFileEntry.getFullPath(), getSerialNumber(), e.getMessage());
                    throw e;
                } finally {
                    if (syncService != null) {
                        syncService.close();
                    }
                }
                return status;
            }
        };
        return performDeviceAction(String.format("sync files %s", remoteFileEntry.getFullPath()),
                syncAction, MAX_RETRY_ATTEMPTS);
    }

    /**
     * Queries the file listing service for a given directory
     *
     * @param remoteFileEntry
     * @throws DeviceNotAvailableException
     */
    FileEntry[] getFileChildren(final FileEntry remoteFileEntry)
            throws DeviceNotAvailableException {
        // time this operation because its known to hang
        FileQueryAction action = new FileQueryAction(remoteFileEntry,
                getIDevice().getFileListingService());
        performDeviceAction("buildFileCache", action, 1 /* one retry */);
        return action.mFileContents;
    }

    private class FileQueryAction implements DeviceAction {

        FileEntry[] mFileContents = null;
        private final FileEntry mRemoteFileEntry;
        private final FileListingService mService;

        FileQueryAction(FileEntry remoteFileEntry, FileListingService service) {
            throwIfNull(remoteFileEntry);
            throwIfNull(service);
            mRemoteFileEntry = remoteFileEntry;
            mService = service;
        }

        @Override
        public boolean run() throws TimeoutException, IOException, AdbCommandRejectedException,
                ShellCommandUnresponsiveException {
            mFileContents = mService.getChildrenSync(mRemoteFileEntry);
            return true;
        }
    }

    /**
     * A {@link FilenameFilter} that rejects hidden (ie starts with ".") files.
     */
    private static class NoHiddenFilesFilter implements FilenameFilter {
        /**
         * {@inheritDoc}
         */
        @Override
        public boolean accept(File dir, String name) {
            return !name.startsWith(".");
        }
    }

    /**
     * helper to get the timezone from the device. Example: "Europe/London"
     */
    private String getDeviceTimezone() {
        try {
            // This may not be set at first, default to GMT in this case.
            String timezone = getProperty("persist.sys.timezone");
            if (timezone != null) {
                return timezone.trim();
            }
        } catch (DeviceNotAvailableException e) {
            // Fall through on purpose
        }
        return "GMT";
    }

    /**
     * Return <code>true</code> if local file is newer than remote file. {@link IFileEntry} being
     * accurate to the minute, in case of equal times, the file will be considered newer.
     */
    @VisibleForTesting
    protected boolean isNewer(File localFile, IFileEntry entry) {
        final String entryTimeString = String.format("%s %s", entry.getDate(), entry.getTime());
        try {
            String timezone = getDeviceTimezone();
            // expected format of a FileEntry's date and time
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            format.setTimeZone(TimeZone.getTimeZone(timezone));
            Date remoteDate = format.parse(entryTimeString);

            long offset = 0;
            try {
                offset = getDeviceTimeOffset(null);
            } catch (DeviceNotAvailableException e) {
                offset = 0;
            }
            CLog.i("Device offset time: %s", offset);

            // localFile.lastModified has granularity of ms, but remoteDate.getTime only has
            // granularity of minutes. Shift remoteDate.getTime() backward by one minute so newly
            // modified files get synced
            return localFile.lastModified() > (remoteDate.getTime() - 60 * 1000 + offset);
        } catch (ParseException e) {
            CLog.e("Error converting remote time stamp %s for %s on device %s", entryTimeString,
                    entry.getFullPath(), getSerialNumber());
        }
        // sync file by default
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String executeAdbCommand(String... cmdArgs) throws DeviceNotAvailableException {
        return executeAdbCommand(getCommandTimeout(), cmdArgs);
    }

    /** {@inheritDoc} */
    @Override
    public String executeAdbCommand(long timeout, String... cmdArgs)
            throws DeviceNotAvailableException {
        return executeAdbCommand(getCommandTimeout(), new HashMap<>(), cmdArgs);
    }

    /** {@inheritDoc} */
    @Override
    public String executeAdbCommand(long timeout, Map<String, String> envMap, String... cmdArgs)
            throws DeviceNotAvailableException {
        final String[] fullCmd = buildAdbCommand(cmdArgs);
        AdbAction adbAction = new AdbAction(timeout, fullCmd, "shell".equals(cmdArgs[0]), envMap);
        performDeviceAction(String.format("adb %s", cmdArgs[0]), adbAction, MAX_RETRY_ATTEMPTS);
        return adbAction.mOutput;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CommandResult executeFastbootCommand(String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        // TODO: fix mixed use of fastboot timeout and command timeout
        return doFastbootCommand(getCommandTimeout(), cmdArgs);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CommandResult executeFastbootCommand(long timeout, String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        return doFastbootCommand(timeout, cmdArgs);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CommandResult executeLongFastbootCommand(String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        return executeLongFastbootCommand(new HashMap<>(), cmdArgs);
    }

    /** {@inheritDoc} */
    @Override
    public CommandResult executeLongFastbootCommand(
            Map<String, String> envVarMap, String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        // TODO: fix mixed use of fastboot timeout and command timeout
        return doFastbootCommand(getLongCommandTimeout(), envVarMap, cmdArgs);
    }

    /**
     * Do a fastboot command with environment variables set
     *
     * @param timeout timeout for the fastboot command
     * @param envVarMap environment variables that needs to be set before execute the fastboot
     *     command
     * @param cmdArgs
     * @return {@link CommandResult} of the fastboot command
     * @throws DeviceNotAvailableException
     * @throws UnsupportedOperationException
     */
    private CommandResult doFastbootCommand(
            final long timeout, Map<String, String> envVarMap, String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        if (!mFastbootEnabled) {
            throw new UnsupportedOperationException(String.format(
                    "Attempted to fastboot on device %s , but fastboot is not available. Aborting.",
                    getSerialNumber()));
        }

        File fastbootTmpDir = getHostOptions().getFastbootTmpDir();
        if (fastbootTmpDir != null) {
            envVarMap.put("TMPDIR", fastbootTmpDir.getAbsolutePath());
        }

        final String[] fullCmd = buildFastbootCommand(cmdArgs);

        for (int i = 0; i < MAX_RETRY_ATTEMPTS; i++) {
            try (CloseableTraceScope ignored = new CloseableTraceScope("fastboot " + cmdArgs[0])) {
                CommandResult result = simpleFastbootCommand(timeout, envVarMap, fullCmd);
                if (!isRecoveryNeeded(result)) {
                    return result;
                }
                CLog.w("Recovery needed after executing fastboot command");
                if (result != null) {
                    CLog.v(
                            "fastboot command output:\nstdout: %s\nstderr:%s",
                            result.getStdout(), result.getStderr());
                }
                recoverDeviceFromBootloader();
            }
        }
        throw new DeviceUnresponsiveException(
                String.format(
                        "Attempted fastboot %s multiple "
                                + "times on device %s without communication success. Aborting.",
                        cmdArgs[0], getSerialNumber()),
                getSerialNumber());
    }

    /**
     * Do a fastboot command
     *
     * @param timeout timeout for the fastboot command
     * @param cmdArgs
     * @return {@link CommandResult} of the fastboot command
     * @throws DeviceNotAvailableException
     * @throws UnsupportedOperationException
     */
    private CommandResult doFastbootCommand(final long timeout, String... cmdArgs)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        return doFastbootCommand(timeout, new HashMap<>(), cmdArgs);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean getUseFastbootErase() {
        return mOptions.getUseFastbootErase();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setUseFastbootErase(boolean useFastbootErase) {
        mOptions.setUseFastbootErase(useFastbootErase);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public CommandResult fastbootWipePartition(String partition)
            throws DeviceNotAvailableException {
        if (mOptions.getUseFastbootErase()) {
            return executeLongFastbootCommand("erase", partition);
        } else {
            return executeLongFastbootCommand("format", partition);
        }
    }

    /**
     * Evaluate the given fastboot result to determine if recovery mode needs to be entered
     *
     * @param fastbootResult the {@link CommandResult} from a fastboot command
     * @return <code>true</code> if recovery mode should be entered, <code>false</code> otherwise.
     */
    private boolean isRecoveryNeeded(CommandResult fastbootResult) {
        if (fastbootResult.getStatus().equals(CommandStatus.TIMED_OUT)) {
            // fastboot commands always time out if devices is not present
            return true;
        } else {
            // check for specific error messages in result that indicate bad device communication
            // and recovery mode is needed
            if (fastbootResult.getStderr() == null ||
                fastbootResult.getStderr().contains("data transfer failure (Protocol error)") ||
                fastbootResult.getStderr().contains("status read failed (No such device)")) {
                CLog.w("Bad fastboot response from device %s. stderr: %s. Entering recovery",
                        getSerialNumber(), fastbootResult.getStderr());
                return true;
            }
        }
        return false;
    }

    /** Get the max time allowed in ms for commands. */
    long getCommandTimeout() {
        return mOptions.getAdbCommandTimeout();
    }

    /**
     * Set the max time allowed in ms for commands.
     */
    void setLongCommandTimeout(long timeout) {
        mLongCmdTimeout = timeout;
    }

    /**
     * Get the max time allowed in ms for commands.
     */
    long getLongCommandTimeout() {
        return mLongCmdTimeout;
    }

    /** Set the max time allowed in ms for commands. */
    void setCommandTimeout(long timeout) {
        mOptions.setAdbCommandTimeout(timeout);
    }

    /**
     * Builds the OS command for the given adb command and args
     */
    private String[] buildAdbCommand(String... commandArgs) {
        return ArrayUtil.buildArray(new String[] {"adb", "-s", getSerialNumber()},
                commandArgs);
    }

    /** Builds the OS command for the given adb shell command session and args */
    protected String[] buildAdbShellCommand(String command, boolean forceExitStatusDetection) {
        // TODO: implement the shell v2 support in ddmlib itself.
        String[] commandArgs =
                QuotationAwareTokenizer.tokenizeLine(
                        command,
                        /** No logging */
                        false);

        String[] exitStatusProbe;
        if (forceExitStatusDetection) {
            exitStatusProbe = new String[] {";", "echo", EXIT_STATUS_DELIMITER + "$?"};
        } else {
            exitStatusProbe = new String[] {};
        }
        return ArrayUtil.buildArray(
                new String[] {"adb", "-s", getSerialNumber(), "shell"},
                commandArgs,
                exitStatusProbe);
    }

    /**
     * Builds the OS command for the given fastboot command and args
     */
    private String[] buildFastbootCommand(String... commandArgs) {
        return ArrayUtil.buildArray(
                new String[] {getFastbootPath(), "-s", getFastbootSerialNumber()}, commandArgs);
    }

    /**
     * Performs an action on this device. Attempts to recover device and optionally retry command if
     * action fails.
     *
     * @param actionDescription a short description of action to be performed. Used for logging
     *     purposes only.
     * @param action the action to be performed
     * @param retryAttempts the retry attempts to make for action if it fails but recovery succeeds
     * @return <code>true</code> if action was performed successfully
     * @throws DeviceNotAvailableException if recovery attempt fails or max attempts done without
     *     success
     */
    protected boolean performDeviceAction(
            String actionDescription, final DeviceAction action, int retryAttempts)
            throws DeviceNotAvailableException {
        Exception lastException = null;
        try (CloseableTraceScope ignored = new CloseableTraceScope(actionDescription)) {
            for (int i = 0; i < retryAttempts + 1; i++) {
                boolean shouldRecover = true;
                try {
                    return action.run();
                } catch (TimeoutException e) {
                    logDeviceActionException(actionDescription, e, false);
                    lastException = e;
                } catch (IOException e) {
                    logDeviceActionException(actionDescription, e, true);
                    lastException = e;
                } catch (InstallException e) {
                    logDeviceActionException(actionDescription, e, true);
                    lastException = e;
                } catch (SyncException e) {
                    logDeviceActionException(actionDescription, e, true);
                    lastException = e;
                    // a SyncException is not necessarily a device communication problem
                    // do additional diagnosis
                    if (!e.getErrorCode().equals(SyncError.BUFFER_OVERRUN)
                            && !e.getErrorCode().equals(SyncError.TRANSFER_PROTOCOL_ERROR)) {
                        // this is a logic problem, doesn't need recovery or to be retried
                        return false;
                    }
                } catch (AdbCommandRejectedException e) {
                    // Workaround to not recover device if TCP adb is used.
                    if (isAdbTcp()
                            && (action instanceof RebootDeviceAction)
                            && ((RebootDeviceAction) action).isFastbootOrBootloader()) {
                        CLog.d(
                                "Ignore AdbCommandRejectedException when TCP device is rebooted"
                                        + " into fastboot.");
                        return true;
                    }
                    lastException = e;
                    logDeviceActionException(actionDescription, e, false);
                } catch (ShellCommandUnresponsiveException e) {
                    // ShellCommandUnresponsiveException is thrown when no output occurs within the
                    // timeout. It doesn't necessarily mean the device is offline.
                    shouldRecover = false;
                    lastException = e;
                    CLog.w(
                            "Command: '%s' on '%s' went over its timeout for outputing a response.",
                            actionDescription, getSerialNumber());
                }
                if (shouldRecover) {
                    recoverDevice();
                }
            }
            if (retryAttempts > 0) {
                throw new DeviceUnresponsiveException(
                        String.format(
                                "Attempted %s multiple times "
                                        + "on device %s without communication success. Aborting.",
                                actionDescription, getSerialNumber()),
                        lastException,
                        getSerialNumber(),
                        DeviceErrorIdentifier.DEVICE_UNRESPONSIVE);
            }
            return false;
        }
    }

    /**
     * Log an entry for given exception
     *
     * @param actionDescription the action's description
     * @param e the exception
     * @param logFullTrace whether the full exception stack trace should be logged
     */
    private void logDeviceActionException(
            String actionDescription, Exception e, boolean logFullTrace) {
        CLog.w("%s (%s) when attempting %s on device %s", e.getClass().getSimpleName(),
                getExceptionMessage(e), actionDescription, getSerialNumber());
        if (logFullTrace) {
            CLog.w(e);
        }
    }

    /**
     * Make a best effort attempt to retrieve a meaningful short descriptive message for given
     * {@link Exception}
     *
     * @param e the {@link Exception}
     * @return a short message
     */
    private String getExceptionMessage(Exception e) {
        StringBuilder msgBuilder = new StringBuilder();
        if (e.getMessage() != null) {
            msgBuilder.append(e.getMessage());
        }
        if (e.getCause() != null) {
            msgBuilder.append(" cause: ");
            msgBuilder.append(e.getCause().getClass().getSimpleName());
            if (e.getCause().getMessage() != null) {
                msgBuilder.append(" (");
                msgBuilder.append(e.getCause().getMessage());
                msgBuilder.append(")");
            }
        }
        return msgBuilder.toString();
    }

    /**
     * Attempts to recover device communication.
     *
     * @throws DeviceNotAvailableException if device is no longer available
     */
    @Override
    public boolean recoverDevice() throws DeviceNotAvailableException {
        getConnection().reconnectForRecovery(getSerialNumber());
        if (mRecoveryMode.equals(RecoveryMode.NONE)) {
            CLog.i("Skipping recovery on %s", getSerialNumber());
            return false;
        }
        CLog.i("Attempting recovery on %s", getSerialNumber());
        InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.RECOVERY_ROUTINE_COUNT, 1);
        long startTime = System.currentTimeMillis();
        try {
            try {
                mRecovery.recoverDevice(mStateMonitor, mRecoveryMode.equals(RecoveryMode.ONLINE));
            } catch (DeviceUnresponsiveException due) {
                RecoveryMode previousRecoveryMode = mRecoveryMode;
                mRecoveryMode = RecoveryMode.NONE;
                try {
                    boolean enabled = enableAdbRoot();
                    CLog.d(
                            "Device Unresponsive during recovery, is root still enabled: %s",
                            enabled);
                } catch (DeviceUnresponsiveException e) {
                    // Ignore exception thrown here to rethrow original exception.
                    CLog.e("Exception occurred during recovery adb root:");
                    CLog.e(e);
                    Throwable cause = e.getCause();
                    if (cause != null && cause instanceof AdbCommandRejectedException) {
                        AdbCommandRejectedException adbException =
                                (AdbCommandRejectedException) cause;
                        if (adbException.isDeviceOffline()
                                || adbException.wasErrorDuringDeviceSelection()) {
                            // Upgrade exception to DNAE to reflect gravity
                            throw new DeviceNotAvailableException(
                                    cause.getMessage(),
                                    adbException,
                                    getSerialNumber(),
                                    DeviceErrorIdentifier.DEVICE_UNAVAILABLE);
                        }
                    }
                }
                mRecoveryMode = previousRecoveryMode;
                throw due;
            }
            if (mRecoveryMode.equals(RecoveryMode.AVAILABLE)) {
                // turn off recovery mode to prevent reentrant recovery
                // TODO: look for a better way to handle this, such as doing postBootUp steps in
                // recovery itself
                mRecoveryMode = RecoveryMode.NONE;
                // this might be a runtime reset - still need to run post boot setup steps
                if (isEncryptionSupported() && isDeviceEncrypted()) {
                    unlockDevice();
                }
                postBootSetup();
                mRecoveryMode = RecoveryMode.AVAILABLE;
            } else if (mRecoveryMode.equals(RecoveryMode.ONLINE)) {
                // turn off recovery mode to prevent reentrant recovery
                // TODO: look for a better way to handle this, such as doing postBootUp steps in
                // recovery itself
                mRecoveryMode = RecoveryMode.NONE;
                enableAdbRoot();
                mRecoveryMode = RecoveryMode.ONLINE;
            }
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.RECOVERY_TIME, System.currentTimeMillis() - startTime);
        }
        CLog.i("Recovery successful for %s", getSerialNumber());
        return true;
    }

    /**
     * Attempts to recover device fastboot communication.
     *
     * @throws DeviceNotAvailableException if device is not longer available
     */
    private void recoverDeviceFromBootloader() throws DeviceNotAvailableException {
        CLog.i("Attempting recovery on %s in bootloader", getSerialNumber());
        mRecovery.recoverDeviceBootloader(mStateMonitor);
        CLog.i("Bootloader recovery successful for %s", getSerialNumber());
    }

    private void recoverDeviceFromFastbootd() throws DeviceNotAvailableException {
        CLog.i("Attempting recovery on %s in fastbootd", getSerialNumber());
        mRecovery.recoverDeviceFastbootd(mStateMonitor);
        CLog.i("Fastbootd recovery successful for %s", getSerialNumber());
    }

    private void recoverDeviceInRecovery() throws DeviceNotAvailableException {
        CLog.i("Attempting recovery on %s in recovery", getSerialNumber());
        mRecovery.recoverDeviceRecovery(mStateMonitor);
        CLog.i("Recovery mode recovery successful for %s", getSerialNumber());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void startLogcat() {
        if (mLogcatReceiver != null) {
            CLog.d("Already capturing logcat for %s, ignoring", getSerialNumber());
            return;
        }
        mLogcatReceiver = createLogcatReceiver();
        mLogcatReceiver.start();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void clearLogcat() {
        if (mLogcatReceiver != null) {
            mLogcatReceiver.clear();
        }
    }

    /** {@inheritDoc} */
    @Override
    @SuppressWarnings("MustBeClosedChecker")
    public InputStreamSource getLogcat() {
        if (mLogcatReceiver == null) {
            if (!(getIDevice() instanceof StubDevice)) {
                TestDeviceState state = getDeviceState();
                if (!TestDeviceState.ONLINE.equals(state)) {
                    CLog.w("Skipping logcat capture, no buffer and device state is '%s'", state);
                } else {
                    CLog.w(
                            "Not capturing logcat for %s in background, returning a logcat dump",
                            getSerialNumber());
                    return getLogcatDump();
                }
            }
            return new ByteArrayInputStreamSource(new byte[0]);
        } else {
            return mLogcatReceiver.getLogcatData();
        }
    }

    /** {@inheritDoc} */
    @Override
    @SuppressWarnings("MustBeClosedChecker")
    public InputStreamSource getLogcat(int maxBytes) {
        if (mLogcatReceiver == null) {
            CLog.w("Not capturing logcat for %s in background, returning a logcat dump "
                    + "ignoring size", getSerialNumber());
            return getLogcatDump();
        } else {
            return mLogcatReceiver.getLogcatData(maxBytes);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getLogcatSince(long date) {
        int deviceApiLevel;
        try {
            deviceApiLevel = getApiLevel();
            if (deviceApiLevel <= 22) {
                CLog.i("Api level too low to use logcat -t 'time' reverting to dump");
                return getLogcatDump();
            }
        } catch (DeviceNotAvailableException e) {
            // For convenience of interface, we catch the DNAE here.
            CLog.e(e);
            return getLogcatDump();
        }

        String dateFormatted;
        if (deviceApiLevel >= 24) {
            // Use 'sssss.mmm' epoch time format supported since API 24.
            dateFormatted = String.format(Locale.US, "%d.%03d", date / 1000, date % 1000);
        } else {
            // Convert date to format needed by the command:
            // 'MM-DD HH:mm:ss.mmm' or 'YYYY-MM-DD HH:mm:ss.mmm'
            SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
            dateFormatted = format.format(new Date(date));
        }

        LargeOutputReceiver largeReceiver = null;
        try {
            // use IDevice directly because we don't want callers to handle
            // DeviceNotAvailableException for this method
            largeReceiver =
                    new LargeOutputReceiver(
                            "getLogcatSince",
                            getSerialNumber(),
                            getOptions().getMaxLogcatDataSize());
            String command =
                    String.format(
                            "%s -t '%s'", LogcatReceiver.getDefaultLogcatCmd(this), dateFormatted);
            getIDevice().executeShellCommand(command, largeReceiver);
            return largeReceiver.getData();
        } catch (IOException|AdbCommandRejectedException|
                ShellCommandUnresponsiveException|TimeoutException e) {
            CLog.w("Failed to get logcat dump from %s: %s", getSerialNumber(), e.getMessage());
            CLog.e(e);
        } finally {
            if (largeReceiver != null) {
                largeReceiver.cancel();
                largeReceiver.delete();
            }
        }
        return new ByteArrayInputStreamSource(new byte[0]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getLogcatDump() {
        long startTime = System.currentTimeMillis();
        LargeOutputReceiver largeReceiver = null;
        try (CloseableTraceScope ignored = new CloseableTraceScope("getLogcatDump")) {
            // use IDevice directly because we don't want callers to handle
            // DeviceNotAvailableException for this method
            largeReceiver =
                    new LargeOutputReceiver(
                            "getLogcatDump",
                            getSerialNumber(),
                            getOptions().getMaxLogcatDataSize());
            // add -d parameter to make this a non blocking call
            getIDevice()
                    .executeShellCommand(
                            LogcatReceiver.getDefaultLogcatCmd(this) + " -d",
                            largeReceiver,
                            LOGCAT_DUMP_TIMEOUT,
                            LOGCAT_DUMP_TIMEOUT,
                            TimeUnit.MILLISECONDS);
            return largeReceiver.getData();
        } catch (IOException e) {
            CLog.w("Failed to get logcat dump from %s: ", getSerialNumber(), e.getMessage());
        } catch (TimeoutException e) {
            CLog.w("Failed to get logcat dump from %s: timeout", getSerialNumber());
        } catch (AdbCommandRejectedException e) {
            CLog.w("Failed to get logcat dump from %s: ", getSerialNumber(), e.getMessage());
        } catch (ShellCommandUnresponsiveException e) {
            CLog.w("Failed to get logcat dump from %s: ", getSerialNumber(), e.getMessage());
        } finally {
            if (largeReceiver != null) {
                largeReceiver.cancel();
                largeReceiver.delete();
            }
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.LOGCAT_DUMP_TIME, System.currentTimeMillis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.LOGCAT_DUMP_COUNT, 1);
        }
        return new ByteArrayInputStreamSource(new byte[0]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stopLogcat() {
        if (mLogcatReceiver != null) {
            mLogcatReceiver.stop();
            mLogcatReceiver = null;
        } else {
            CLog.w("Attempting to stop logcat when not capturing for %s", getSerialNumber());
        }
    }

    /** Factory method to create a {@link LogcatReceiver}. */
    @VisibleForTesting
    LogcatReceiver createLogcatReceiver() {
        String logcatOptions = mOptions.getLogcatOptions();
        if (SystemUtil.isLocalMode()) {
            mLogStartDelay = 0;
        }
        if (logcatOptions == null) {
            return new LogcatReceiver(this, mOptions.getMaxLogcatDataSize(), mLogStartDelay);
        } else {
            return new LogcatReceiver(
                    this,
                    String.format("%s %s", LogcatReceiver.getDefaultLogcatCmd(this), logcatOptions),
                    mOptions.getMaxLogcatDataSize(),
                    mLogStartDelay);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getBugreport() {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean logBugreport(String dataName, ITestLogger listener) {
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Bugreport takeBugreport() {
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getBugreportz() {
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public boolean logAnrs(ITestLogger logger) throws DeviceNotAvailableException {
        if (!doesFileExist(ANRS_PATH)) {
            CLog.d("No ANRs at %s", ANRS_PATH);
            return true;
        }
        boolean root = enableAdbRoot();
        if (!root) {
            CLog.d("Skipping logAnrs, need to be root.");
        }
        File localDir = null;
        long startTime = System.currentTimeMillis();
        try {
            localDir = FileUtil.createTempDir("pulled-anrs");
            boolean success = pullDir(ANRS_PATH, localDir);
            if (!success) {
                CLog.w("Failed to pull %s", ANRS_PATH);
                return false;
            }
            if (localDir.listFiles().length == 0) {
                return true;
            }
            for (File f : localDir.listFiles()) {
                try (FileInputStreamSource source = new FileInputStreamSource(f)) {
                    String name = f.getName();
                    LogDataType type = LogDataType.ANRS;
                    if (name.startsWith("dumptrace")) {
                        type = LogDataType.DUMPTRACE;
                    }
                    logger.testLog(name, type, source);
                }
            }
        } catch (IOException e) {
            CLog.e(e);
            return false;
        } finally {
            FileUtil.recursiveDelete(localDir);
        }
        InvocationMetricLogger.addInvocationMetrics(
                InvocationMetricKey.ANR_TIME, System.currentTimeMillis() - startTime);
        InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.ANR_COUNT, 1);
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getScreenshot() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Screenshot");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getScreenshot(String format) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Screenshot");
    }

    /** {@inheritDoc} */
    @Override
    public InputStreamSource getScreenshot(String format, boolean rescale)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Screenshot");
    }

    /** {@inheritDoc} */
    @Override
    public InputStreamSource getScreenshot(long displayId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Screenshot");
    }

    /** {@inheritDoc} */
    @Override
    public void clearLastConnectedWifiNetwork() {
        mLastConnectedWifiSsid = null;
        mLastConnectedWifiPsk = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk)
            throws DeviceNotAvailableException {
        return connectToWifiNetwork(wifiSsid, wifiPsk, false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connectToWifiNetwork(String wifiSsid, String wifiPsk, boolean scanSsid)
            throws DeviceNotAvailableException {
        LinkedHashMap<String, String> ssidToPsk = new LinkedHashMap<>();
        ssidToPsk.put(wifiSsid, wifiPsk);
        return connectToWifiNetwork(ssidToPsk, scanSsid);
    }

    /** {@inheritDoc}f */
    @Override
    public boolean connectToWifiNetwork(Map<String, String> wifiSsidToPsk)
            throws DeviceNotAvailableException {
        return connectToWifiNetwork(wifiSsidToPsk, false);
    }

    /** {@inheritDoc} */
    @Override
    public boolean connectToWifiNetwork(Map<String, String> wifiSsidToPsk, boolean scanSsid)
            throws DeviceNotAvailableException {
        // Clears the last connected wifi network.
        mLastConnectedWifiSsid = null;
        mLastConnectedWifiPsk = null;

        // Connects to wifi network. It retries up to {@link TestDeviceOptions@getWifiAttempts()}
        // times
        Random rnd = new Random();
        int backoffSlotCount = 2;
        int slotTime = mOptions.getWifiRetryWaitTime();
        int waitTime = 0;
        long startTime = mClock.millis();
        try (CloseableTraceScope ignored = new CloseableTraceScope("connectToWifiNetwork")) {
            for (int i = 1; i <= mOptions.getWifiAttempts(); i++) {
                boolean failedToEnableWifi = false;
                for (Map.Entry<String, String> ssidToPsk : wifiSsidToPsk.entrySet()) {
                    String wifiSsid = ssidToPsk.getKey();
                    String wifiPsk = Strings.emptyToNull(ssidToPsk.getValue());

                    InvocationMetricLogger.addInvocationMetrics(
                            InvocationMetricKey.WIFI_CONNECT_RETRY_COUNT, i);
                    CLog.i("Connecting to wifi network %s on %s", wifiSsid, getSerialNumber());
                    IWifiHelper wifi = null;
                    if (!getOptions().useCmdWifiCommands()
                            || !enableAdbRoot()
                            || getApiLevel() < 31) {
                        wifi = createWifiHelper(false);
                    } else {
                        wifi = createWifiHelper(true);
                    }
                    WifiConnectionResult result =
                            wifi.connectToNetwork(
                                    wifiSsid,
                                    wifiPsk,
                                    mOptions.getConnCheckUrl(),
                                    scanSsid,
                                    mOptions.getDefaultNetworkType());

                    final Map<String, String> wifiInfo = wifi.getWifiInfo();
                    if (WifiConnectionResult.SUCCESS.equals(result)) {
                        CLog.i(
                                "Successfully connected to wifi network %s(%s) on %s",
                                wifiSsid, wifiInfo.get("bssid"), getSerialNumber());
                        InvocationMetricLogger.addInvocationMetrics(
                                InvocationMetricKey.WIFI_AP_NAME, wifiSsid);
                        mLastConnectedWifiSsid = wifiSsid;
                        mLastConnectedWifiPsk = wifiPsk;

                        return true;
                    } else if (WifiConnectionResult.FAILED_TO_ENABLE.equals(result)) {
                        CLog.w("Failed to enable wifi");
                        failedToEnableWifi = true;
                    } else {
                        failedToEnableWifi = false;
                        CLog.w(
                                "Failed to connect to wifi network %s(%s) on %s on attempt %d of"
                                        + " %d",
                                wifiSsid,
                                wifiInfo.get("bssid"),
                                getSerialNumber(),
                                i,
                                mOptions.getWifiAttempts());
                    }
                }
                if (mClock.millis() - startTime >= mOptions.getMaxWifiConnectTime()) {
                    CLog.e(
                            "Failed to connect to wifi after %d ms. Aborting.",
                            mOptions.getMaxWifiConnectTime());
                    break;
                }
                // Do not sleep for the last iteration and when failed to enable wifi.
                if (i < mOptions.getWifiAttempts() && !failedToEnableWifi) {
                    if (mOptions.isWifiExpoRetryEnabled()) {
                        // use binary exponential back-offs when retrying.
                        waitTime = rnd.nextInt(backoffSlotCount) * slotTime;
                        backoffSlotCount *= 2;
                    }
                    CLog.e(
                            "Waiting for %d ms before reconnecting to %s...",
                            waitTime, wifiSsidToPsk.keySet().toString());
                    getRunUtil().sleep(waitTime);
                }
            }
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.WIFI_CONNECT_TIME, mClock.millis() - startTime);
            InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.WIFI_CONNECT_COUNT, 1);
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean checkConnectivity() throws DeviceNotAvailableException {
        IWifiHelper wifi = createWifiHelper();
        return wifi.checkConnectivity(mOptions.getConnCheckUrl());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk)
            throws DeviceNotAvailableException {
        return connectToWifiNetworkIfNeeded(wifiSsid, wifiPsk, false);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean connectToWifiNetworkIfNeeded(String wifiSsid, String wifiPsk, boolean scanSsid)
            throws DeviceNotAvailableException {
        if (!checkConnectivity())  {
            return connectToWifiNetwork(wifiSsid, wifiPsk, scanSsid);
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isWifiEnabled() throws DeviceNotAvailableException {
        final IWifiHelper wifi = createWifiHelper();
        try {
            return wifi.isWifiEnabled();
        } catch (RuntimeException e) {
            CLog.w("Failed to create WifiHelper: %s", e.getMessage());
            return false;
        }
    }

    /**
     * Checks that the device is currently successfully connected to given wifi SSID.
     *
     * @param wifiSSID the wifi ssid
     * @return <code>true</code> if device is currently connected to wifiSSID and has network
     *         connectivity. <code>false</code> otherwise
     * @throws DeviceNotAvailableException if connection with device was lost
     */
    boolean checkWifiConnection(String wifiSSID) throws DeviceNotAvailableException {
        CLog.i("Checking connection with wifi network %s on %s", wifiSSID, getSerialNumber());
        final IWifiHelper wifi = createWifiHelper();
        // getSSID returns SSID as "SSID"
        final String quotedSSID = String.format("\"%s\"", wifiSSID);

        boolean test = wifi.isWifiEnabled();
        CLog.v("%s: wifi enabled? %b", getSerialNumber(), test);

        if (test) {
            final String actualSSID = wifi.getSSID();
            test = quotedSSID.equals(actualSSID);
            CLog.v("%s: SSID match (%s, %s, %b)", getSerialNumber(), quotedSSID, actualSSID, test);
        }
        if (test) {
            test = wifi.hasValidIp();
            CLog.v("%s: validIP? %b", getSerialNumber(), test);
        }
        if (test) {
            test = checkConnectivity();
            CLog.v("%s: checkConnectivity returned %b", getSerialNumber(), test);
        }
        return test;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean disconnectFromWifi() throws DeviceNotAvailableException {
        CLog.i("Disconnecting from wifi on %s", getSerialNumber());
        // Clears the last connected wifi network.
        mLastConnectedWifiSsid = null;
        mLastConnectedWifiPsk = null;

        IWifiHelper wifi = createWifiHelper();
        return wifi.disconnectFromNetwork();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getIpAddress() throws DeviceNotAvailableException {
        IWifiHelper wifi = createWifiHelper();
        return wifi.getIpAddress();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean enableNetworkMonitor() throws DeviceNotAvailableException {
        mNetworkMonitorEnabled = false;

        IWifiHelper wifi = createWifiHelper();
        wifi.stopMonitor();
        if (wifi.startMonitor(NETWORK_MONITOR_INTERVAL, mOptions.getConnCheckUrl())) {
            mNetworkMonitorEnabled = true;
            return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean disableNetworkMonitor() throws DeviceNotAvailableException {
        mNetworkMonitorEnabled = false;

        IWifiHelper wifi = createWifiHelper();
        List<Long> samples = wifi.stopMonitor();
        if (!samples.isEmpty()) {
            int failures = 0;
            long totalLatency = 0;
            for (Long sample : samples) {
                if (sample < 0) {
                    failures += 1;
                } else {
                    totalLatency += sample;
                }
            }
            double failureRate = failures * 100.0 / samples.size();
            double avgLatency = 0.0;
            if (failures < samples.size()) {
                avgLatency = totalLatency / (samples.size() - failures);
            }
            CLog.d("[metric] url=%s, window=%ss, failure_rate=%.2f%%, latency_avg=%.2f",
                    mOptions.getConnCheckUrl(), samples.size() * NETWORK_MONITOR_INTERVAL / 1000,
                    failureRate, avgLatency);
        }
        return true;
    }

    /**
     * Create a {@link WifiHelper} to use
     *
     * <p>
     *
     * @throws DeviceNotAvailableException
     */
    @VisibleForTesting
    IWifiHelper createWifiHelper() throws DeviceNotAvailableException {
        // current wifi helper won't work on AndroidNativeDevice
        // TODO: create a new Wifi helper with supported feature of AndroidNativeDevice when
        // we learn what is available.
        throw new UnsupportedOperationException("Wifi helper is not supported.");
    }

    /**
     * Create a {@link WifiHelper} to use
     *
     * @param useV2 Whether to use WifiHelper v2 which does not install any apk.
     *     <p>
     * @throws DeviceNotAvailableException
     */
    @VisibleForTesting
    IWifiHelper createWifiHelper(boolean useV2) throws DeviceNotAvailableException {
        // current wifi helper won't work on AndroidNativeDevice
        // TODO: create a new Wifi helper with supported feature of AndroidNativeDevice when
        // we learn what is available.
        throw new UnsupportedOperationException("Wifi helper is not supported.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean clearErrorDialogs() throws DeviceNotAvailableException {
        CLog.e("No support for Screen's features");
        return false;
    }

    /** {@inheritDoc} */
    @Override
    public KeyguardControllerState getKeyguardState() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for keyguard querying.");
    }

    IDeviceStateMonitor getDeviceStateMonitor() {
        return mStateMonitor;
    }

    /** {@inheritDoc} */
    @Override
    public void postBootSetup() throws DeviceNotAvailableException {
        if (getOptions().shouldDisableReboot()) {
            return;
        }
        getConnection().reconnect(getSerialNumber());
        CLog.d("postBootSetup started");
        long startTime = System.currentTimeMillis();
        try (CloseableTraceScope ignored = new CloseableTraceScope("postBootSetup")) {
            enableAdbRoot();
            prePostBootSetup();
            for (String command : mOptions.getPostBootCommands()) {
                long start = System.currentTimeMillis();
                try (CloseableTraceScope cmdTrace = new CloseableTraceScope(command)) {
                    executeShellCommand(command);
                }
                if (command.startsWith("sleep")) {
                    InvocationMetricLogger.addInvocationPairMetrics(
                            InvocationMetricKey.host_sleep, start, System.currentTimeMillis());
                }
            }
        } finally {
            long elapsed = System.currentTimeMillis() - startTime;
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.POSTBOOT_SETUP_TIME, elapsed);
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.POSTBOOT_SETUP_COUNT, 1);
            CLog.d("postBootSetup done: %s", TimeUtil.formatElapsedTime(elapsed));
        }
    }

    /**
     * Allows each device type (AndroidNativeDevice, TestDevice) to override this method for
     * specific post boot setup.
     *
     * @throws DeviceNotAvailableException
     */
    protected void prePostBootSetup() throws DeviceNotAvailableException {
        // Empty on purpose.
    }

    /**
     * Ensure wifi connection is re-established after boot. This is intended to be called after TF
     * initiated reboots(ones triggered by {@link #reboot()}) only.
     *
     * @throws DeviceNotAvailableException
     */
    void postBootWifiSetup() throws DeviceNotAvailableException {
        CLog.d("postBootWifiSetup started");
        long startTime = System.currentTimeMillis();
        try (CloseableTraceScope ignored = new CloseableTraceScope("postBootWifiSetup")) {
            if (mLastConnectedWifiSsid != null) {
                reconnectToWifiNetwork();
            }
            if (mNetworkMonitorEnabled) {
                if (!enableNetworkMonitor()) {
                    CLog.w(
                            "Failed to enable network monitor on %s after reboot",
                            getSerialNumber());
                }
            }
        } finally {
            long elapsed = System.currentTimeMillis() - startTime;
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.POSTBOOT_WIFI_SETUP_TIME, elapsed);
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.POSTBOOT_WIFI_SETUP_COUNT, 1);
            CLog.d("postBootWifiSetup done: %s", TimeUtil.formatElapsedTime(elapsed));
        }
    }

    void reconnectToWifiNetwork() throws DeviceNotAvailableException {
        // First, wait for wifi to re-connect automatically.
        long startTime = System.currentTimeMillis();
        boolean isConnected = checkConnectivity();
        while (!isConnected && (System.currentTimeMillis() - startTime) < WIFI_RECONNECT_TIMEOUT) {
            getRunUtil().sleep(WIFI_RECONNECT_CHECK_INTERVAL);
            isConnected = checkConnectivity();
        }

        if (isConnected) {
            return;
        }

        // If wifi is still not connected, try to re-connect on our own.
        final String wifiSsid = mLastConnectedWifiSsid;
        if (!connectToWifiNetworkIfNeeded(mLastConnectedWifiSsid, mLastConnectedWifiPsk)) {
            throw new NetworkNotAvailableException(
                    String.format("Failed to connect to wifi network %s on %s after reboot",
                            wifiSsid, getSerialNumber()));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void rebootIntoBootloader()
            throws DeviceNotAvailableException, UnsupportedOperationException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot into Bootloader");
            return;
        }
        rebootIntoFastbootInternal(true);
    }

    /** {@inheritDoc} */
    @Override
    public void rebootIntoFastbootd()
            throws DeviceNotAvailableException, UnsupportedOperationException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot into Fastbootd");
            return;
        }
        rebootIntoFastbootInternal(false);
    }

    /**
     * Reboots the device into bootloader or fastbootd mode.
     *
     * @param isBootloader true to boot the device into bootloader mode, false to boot the device
     *     into fastbootd mode.
     * @throws DeviceNotAvailableException if connection with device is lost and cannot be
     *     recovered.
     */
    private void rebootIntoFastbootInternal(boolean isBootloader)
            throws DeviceNotAvailableException {
        invalidatePropertyCache();
        final RebootMode mode =
                isBootloader ? RebootMode.REBOOT_INTO_BOOTLOADER : RebootMode.REBOOT_INTO_FASTBOOTD;
        if (!mFastbootEnabled) {
            throw new UnsupportedOperationException(
                    String.format("Fastboot is not available and cannot reboot into %s", mode));
        }
        // Force wait for snapuserd in progress just to be sure
        waitForSnapuserd(SnapuserdWaitPhase.BLOCK_BEFORE_RELEASING);
        long startTime = System.currentTimeMillis();

        try (CloseableTraceScope ignored =
                new CloseableTraceScope("reboot_in_" + mode.toString())) {
            // Update fastboot serial number before entering fastboot mode
            mStateMonitor.setFastbootSerialNumber(getFastbootSerialNumber());

            // If we go to bootloader, it's probably for flashing so ensure we re-check the provider
            mShouldSkipContentProviderSetup = false;
            CLog.i(
                    "Rebooting device %s in state %s into %s",
                    getSerialNumber(), getDeviceState(), mode);
            if (isStateBootloaderOrFastbootd()) {
                CLog.i(
                        "device %s already in %s. Rebooting anyway",
                        getSerialNumber(), getDeviceState());
                InvocationMetricLogger.addInvocationMetrics(
                        InvocationMetricKey.BOOTLOADER_SAME_STATE_REBOOT, 1);
                executeFastbootCommand(String.format("reboot-%s", mode));
            } else {
                CLog.i("Booting device %s into %s", getSerialNumber(), mode);
                doAdbReboot(mode, null);
            }

            // We want to wait on a command that verifies we've rebooted.
            // However, it is possible to issue this command too quickly and get
            // a response before the device has begun the reboot process (see
            // b/242200753).
            // While not as clean as we'd like, we wait 1.5 seconds before
            // issuing any waiting commands, as devices generally take much
            // longer than 1.5 seconds to reboot anyway.
            getRunUtil().sleep(1500);

            if (RebootMode.REBOOT_INTO_FASTBOOTD.equals(mode)
                    && getHostOptions().isFastbootdEnable()) {
                if (!mStateMonitor.waitForDeviceFastbootd(
                        getFastbootPath(), mOptions.getFastbootTimeout())) {
                    recoverDeviceFromFastbootd();
                }
            } else {
                waitForDeviceBootloader();
            }
        } finally {
            long elapsedTime = System.currentTimeMillis() - startTime;
            if (RebootMode.REBOOT_INTO_FASTBOOTD.equals(mode)) {
                InvocationMetricLogger.addInvocationMetrics(
                        InvocationMetricKey.FASTBOOTD_REBOOT_TIME, elapsedTime);
                InvocationMetricLogger.addInvocationMetrics(
                        InvocationMetricKey.FASTBOOTD_REBOOT_COUNT, 1);
            } else {
                InvocationMetricLogger.addInvocationMetrics(
                        InvocationMetricKey.BOOTLOADER_REBOOT_TIME, elapsedTime);
                InvocationMetricLogger.addInvocationMetrics(
                        InvocationMetricKey.BOOTLOADER_REBOOT_COUNT, 1);
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean isStateBootloaderOrFastbootd() {
        return TestDeviceState.FASTBOOT.equals(getDeviceState())
                || TestDeviceState.FASTBOOTD.equals(getDeviceState());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void reboot() throws DeviceNotAvailableException {
        reboot(null);
    }

    /** {@inheritDoc} */
    @Override
    public void reboot(@Nullable String reason) throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d("'%s' action is disabled during reboot callback. Ignoring.", "Reboot");
            return;
        }
        internalRebootUntilOnline(reason);

        RecoveryMode cachedRecoveryMode = getRecoveryMode();
        setRecoveryMode(RecoveryMode.ONLINE);

        if (isEncryptionSupported() && isDeviceEncrypted()) {
            unlockDevice();
        }

        setRecoveryMode(cachedRecoveryMode);

        try (CloseableTraceScope ignored =
                new CloseableTraceScope("reboot_waitForDeviceAvailable")) {
            waitForDeviceAvailable(mOptions.getRebootTimeout());
        }
        postBootSetup();
        postBootWifiSetup();
        // notify of reboot end here. Full reboots will end here as well as reboots from Bootloader
        // or Fastboot mode.
        notifyRebootEnded();
    }

    @Override
    public void rebootUserspace() throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d("'%s' action is disabled during reboot callback. Ignoring.", "Reboot Userspace");
            return;
        }
        rebootUserspaceUntilOnline();

        RecoveryMode cachedRecoveryMode = getRecoveryMode();
        setRecoveryMode(RecoveryMode.ONLINE);

        if (isEncryptionSupported()) {
            if (isDeviceEncrypted()) {
                CLog.e("Device is encrypted after userspace reboot!");
                unlockDevice();
            }
        }

        setRecoveryMode(cachedRecoveryMode);

        waitForDeviceAvailable(mOptions.getRebootTimeout());
        postBootSetup();
        postBootWifiSetup();
    }

    @Override
    public void rebootUntilOnline() throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot Until Online");
            return;
        }
        try {
            internalRebootUntilOnline(null);
        } finally {
            if (!mDeviceActionReceivers.isEmpty()) {
                CLog.d(
                        "DeviceActionReceivers were not notified after rebootUntilOnline on %s.",
                        getSerialNumber());
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public void rebootUntilOnline(@Nullable String reason) throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot Until Online");
            return;
        }
        try {
            internalRebootUntilOnline(reason);
        } finally {
            if (!mDeviceActionReceivers.isEmpty()) {
                CLog.d(
                        "DeviceActionReceivers were not notified after rebootUntilOnline on %s.",
                        getSerialNumber());
            }
        }
    }

    private void internalRebootUntilOnline(@Nullable String reason)
            throws DeviceNotAvailableException {
        long rebootStart = System.currentTimeMillis();
        try (CloseableTraceScope ignored = new CloseableTraceScope("rebootUntilOnline")) {
            // Invalidate cache before reboots
            mPropertiesCache.invalidateAll();
            doReboot(RebootMode.REBOOT_FULL, reason);
            RecoveryMode cachedRecoveryMode = getRecoveryMode();
            setRecoveryMode(RecoveryMode.ONLINE);
            waitForDeviceOnline();
            enableAdbRoot();
            setRecoveryMode(cachedRecoveryMode);
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.ADB_REBOOT_TIME, System.currentTimeMillis() - rebootStart);
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.ADB_REBOOT_ROUTINE_COUNT, 1);
        }
    }

    @Override
    public void rebootUserspaceUntilOnline() throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot Userspace Until Online");
            return;
        }
        doReboot(RebootMode.REBOOT_USERSPACE, null);
        RecoveryMode cachedRecoveryMode = getRecoveryMode();
        setRecoveryMode(RecoveryMode.ONLINE);
        waitForDeviceOnline();
        enableAdbRoot();
        setRecoveryMode(cachedRecoveryMode);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void rebootIntoRecovery() throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot into Recovery");
            return;
        }
        if (isStateBootloaderOrFastbootd()) {
            CLog.w("device %s in fastboot when requesting boot to recovery. " +
                    "Rebooting to userspace first.", getSerialNumber());
            internalRebootUntilOnline(null);
        }
        doAdbReboot(RebootMode.REBOOT_INTO_RECOVERY, null);
        if (!waitForDeviceInRecovery(mOptions.getAdbRecoveryTimeout())) {
            recoverDeviceInRecovery();
        }
    }


    /** {@inheritDoc} */
    @Override
    public void rebootIntoSideload() throws DeviceNotAvailableException {
        rebootIntoSideload(false);
    }
    /** {@inheritDoc} */
    @Override
    public void rebootIntoSideload(boolean autoReboot) throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Reboot into Sideload");
            return;
        }
        if (isStateBootloaderOrFastbootd()) {
            CLog.w(
                    "device %s in fastboot when requesting boot to sideload. "
                            + "Rebooting to userspace first.",
                    getSerialNumber());
            internalRebootUntilOnline(null);
        }
        final RebootMode rebootMode;
        if (autoReboot) {
            rebootMode = RebootMode.REBOOT_INTO_SIDELOAD_AUTO_REBOOT;
        } else {
            rebootMode = RebootMode.REBOOT_INTO_SIDELOAD;
        }
        doAdbReboot(rebootMode, null);
        if (!waitForDeviceInSideload(mOptions.getAdbRecoveryTimeout())) {
            // using recovery mode because sideload is a sub-mode under recovery
            recoverDeviceInRecovery();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void nonBlockingReboot() throws DeviceNotAvailableException {
        if (isInRebootCallback()) {
            CLog.d(
                    "'%s' action is disabled during reboot callback. Ignoring.",
                    "Non Blocking Reboot");
            return;
        }
        try {
            doReboot(RebootMode.REBOOT_FULL, null);
        } finally {
            if (!mDeviceActionReceivers.isEmpty()) {
                CLog.d(
                        "DeviceActionReceivers were not notified after nonBlockingReboot on %s.",
                        getSerialNumber());
            }
        }
    }

    /**
     * A mode of a reboot.
     *
     * <p>Source of truth for available modes is defined in init.
     */
    @VisibleForTesting
    protected enum RebootMode {
        REBOOT_FULL(""),
        REBOOT_USERSPACE("userspace"),
        REBOOT_INTO_FASTBOOTD("fastboot"),
        REBOOT_INTO_BOOTLOADER("bootloader"),
        REBOOT_INTO_SIDELOAD("sideload"),
        REBOOT_INTO_SIDELOAD_AUTO_REBOOT("sideload-auto-reboot"),
        REBOOT_INTO_RECOVERY("recovery");

        private final String mRebootTarget;

        RebootMode(String rebootTarget) {
            mRebootTarget = rebootTarget;
        }

        @Nullable
        String formatRebootCommand(@Nullable String reason) {
            if (this == REBOOT_FULL) {
                return Strings.isNullOrEmpty(reason) ? null : reason;
            } else {
                return Strings.isNullOrEmpty(reason) ? mRebootTarget : mRebootTarget + "," + reason;
            }
        }

        @Override
        public String toString() {
            return mRebootTarget;
        }
    }

    /**
     * Trigger a reboot of the device, offers no guarantee of the device state after the call.
     *
     * @param rebootMode a mode of this reboot
     * @param reason reason for this reboot
     * @throws DeviceNotAvailableException
     * @throws UnsupportedOperationException
     */
    @VisibleForTesting
    void doReboot(RebootMode rebootMode, @Nullable final String reason)
            throws DeviceNotAvailableException, UnsupportedOperationException {
        // Track Tradefed reboot time
        mLastTradefedRebootTime = System.currentTimeMillis();

        if (isStateBootloaderOrFastbootd()) {
            CLog.i("device %s in %s. Rebooting to userspace.", getSerialNumber(), getDeviceState());
            executeFastbootCommand("reboot");
        } else {
            if (mOptions.shouldDisableReboot()) {
                CLog.i("Device reboot disabled by options, skipped.");
                return;
            }
            if (reason == null) {
                CLog.i("Rebooting device %s mode: %s", getSerialNumber(), rebootMode.name());
            } else {
                CLog.i(
                        "Rebooting device %s mode: %s reason: %s",
                        getSerialNumber(), rebootMode.name(), reason);
            }
            doAdbReboot(rebootMode, reason);
            postAdbReboot();
        }
    }

    /**
     * Possible extra actions that can be taken after a reboot.
     *
     * @throws DeviceNotAvailableException
     */
    protected void postAdbReboot() throws DeviceNotAvailableException {
        // Check if device shows as unavailable (as expected after reboot).
        boolean notAvailable = waitForDeviceNotAvailable(DEFAULT_UNAVAILABLE_TIMEOUT);
        if (!notAvailable) {
            CLog.w("Did not detect device %s becoming unavailable after reboot", getSerialNumber());
        }
        getConnection().reconnect(getSerialNumber());
    }

    /**
     * Perform a adb reboot.
     *
     * @param rebootMode a mode of this reboot.
     * @param reason for this reboot.
     * @throws DeviceNotAvailableException
     */
    protected void doAdbReboot(RebootMode rebootMode, @Nullable final String reason)
            throws DeviceNotAvailableException {
        getConnection().notifyAdbRebootCalled();
        DeviceAction rebootAction = createRebootDeviceAction(rebootMode, reason);
        performDeviceAction("reboot", rebootAction, MAX_RETRY_ATTEMPTS);
    }

    /**
     * Create a {@link RebootDeviceAction} to be used when performing a reboot action.
     *
     * @param rebootMode a mode of this reboot.
     * @param reason for this reboot.
     * @return the created {@link RebootDeviceAction}.
     */
    protected RebootDeviceAction createRebootDeviceAction(
            RebootMode rebootMode, @Nullable final String reason) {
        return new RebootDeviceAction(rebootMode, reason);
    }

    /**
     * Wait to see the device going unavailable (stop reporting to adb).
     *
     * @param operationDesc The name of the operation that is waiting for unavailable.
     * @param time The time to wait for unavailable to occur.
     * @return True if device did become unavailable.
     */
    protected boolean waitForDeviceNotAvailable(String operationDesc, long time) {
        // TODO: a bit of a race condition here. Would be better to start a
        // before the operation
        if (!mStateMonitor.waitForDeviceNotAvailable(time)) {
            // above check is flaky, ignore till better solution is found
            CLog.w("Did not detect device %s becoming unavailable after %s", getSerialNumber(),
                    operationDesc);
            return false;
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForDeviceNotAvailable(long waitTime) {
        return mStateMonitor.waitForDeviceNotAvailable(waitTime);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean enableAdbRoot() throws DeviceNotAvailableException {
        // adb root is a relatively intensive command, so do a brief check first to see
        // if its necessary or not
        if (isAdbRoot()) {
            CLog.i("adb is already running as root on %s", getSerialNumber());
            // Still check for online, in some case we could see the root, but device could be
            // very early in its cycle.
            waitForDeviceOnline();
            return true;
        }
        // Don't enable root if user requested no root
        if (!isEnableAdbRoot()) {
            CLog.i("\"enable-root\" set to false; ignoring 'adb root' request");
            return false;
        }
        InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.ADB_ROOT_ROUTINE_COUNT, 1);
        long startTime = System.currentTimeMillis();
        try (CloseableTraceScope ignored = new CloseableTraceScope("adb_root")) {
            CLog.i("adb root on device %s", getSerialNumber());
            int attempts = MAX_RETRY_ATTEMPTS + 1;
            for (int i = 1; i <= attempts; i++) {
                String output = executeAdbCommand("root");
                // wait for device to disappear from adb
                boolean res =
                        waitForDeviceNotAvailable(
                                "root", getOptions().getAdbRootUnavailableTimeout());
                if (!res && TestDeviceState.ONLINE.equals(getDeviceState())) {
                    if (isAdbRoot()) {
                        return true;
                    }
                }

                postAdbRootAction();

                // wait for device to be back online
                waitForDeviceOnline();

                if (isAdbRoot()) {
                    return true;
                }
                CLog.w(
                        "'adb root' on %s unsuccessful on attempt %d of %d. Output: '%s'",
                        getSerialNumber(), i, attempts, output);
            }
            return false;
        } finally {
            InvocationMetricLogger.addInvocationMetrics(
                    InvocationMetricKey.ADB_ROOT_TIME, System.currentTimeMillis() - startTime);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean disableAdbRoot() throws DeviceNotAvailableException {
        if (!isAdbRoot()) {
            CLog.i("adb is already unroot on %s", getSerialNumber());
            return true;
        }

        CLog.i("adb unroot on device %s", getSerialNumber());
        int attempts = MAX_RETRY_ATTEMPTS + 1;
        for (int i=1; i <= attempts; i++) {
            String output = executeAdbCommand("unroot");
            // wait for device to disappear from adb
            waitForDeviceNotAvailable("unroot", 5 * 1000);

            postAdbUnrootAction();

            // wait for device to be back online
            waitForDeviceOnline();

            if (!isAdbRoot()) {
                return true;
            }
            CLog.w("'adb unroot' on %s unsuccessful on attempt %d of %d. Output: '%s'",
                    getSerialNumber(), i, attempts, output);
        }
        return false;
    }

    /**
     * Override if the device needs some specific actions to be taken after adb root and before the
     * device is back online.
     * Default implementation doesn't include any addition actions.
     * adb root is not guaranteed to be enabled at this stage.
     * @throws DeviceNotAvailableException
     */
    public void postAdbRootAction() throws DeviceNotAvailableException {
        getConnection().reconnect(getSerialNumber());
    }

    /**
     * Override if the device needs some specific actions to be taken after adb unroot and before
     * the device is back online.
     * Default implementation doesn't include any additional actions.
     * adb root is not guaranteed to be disabled at this stage.
     * @throws DeviceNotAvailableException
     */
    public void postAdbUnrootAction() throws DeviceNotAvailableException {
        getConnection().reconnect(getSerialNumber());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isAdbRoot() throws DeviceNotAvailableException {
        String output = executeShellCommand("id");
        return output.contains("uid=0(root)");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean unlockDevice() throws DeviceNotAvailableException,
            UnsupportedOperationException {
        if (!isEncryptionSupported()) {
            throw new UnsupportedOperationException(String.format("Can't unlock device %s: "
                    + "encryption not supported", getSerialNumber()));
        }

        if (!isDeviceEncrypted()) {
            CLog.d("Device %s is not encrypted, skipping", getSerialNumber());
            return true;
        }
        String encryptionType = getProperty("ro.crypto.type");
        if (!"block".equals(encryptionType)) {
            CLog.d(
                    "Skipping unlockDevice since it's not encrypted. ro.crypto.type=%s",
                    encryptionType);
            return true;
        }

        CLog.i("Unlocking device %s", getSerialNumber());

        enableAdbRoot();

        // FIXME: currently, vcd checkpw can return an empty string when it never should.  Try 3
        // times.
        String output;
        int i = 0;
        do {
            // Enter the password. Output will be:
            // "200 [X] -1" if the password has already been entered correctly,
            // "200 [X] 0" if the password is entered correctly,
            // "200 [X] N" where N is any positive number if the password is incorrect,
            // any other string if there is an error.
            output = executeShellCommand(String.format("vdc cryptfs checkpw \"%s\"",
                    ENCRYPTION_PASSWORD)).trim();

            if (output.startsWith("200 ") && output.endsWith(" -1")) {
                return true;
            }

            if (!output.isEmpty() && !(output.startsWith("200 ") && output.endsWith(" 0"))) {
                CLog.e("checkpw gave output '%s' while trying to unlock device %s",
                        output, getSerialNumber());
                return false;
            }

            getRunUtil().sleep(500);
        } while (output.isEmpty() && ++i < 3);

        if (output.isEmpty()) {
            CLog.e("checkpw gave no output while trying to unlock device %s");
        }

        // Restart the framework. Output will be:
        // "200 [X] 0" if the user data partition can be mounted,
        // "200 [X] -1" if the user data partition can not be mounted (no correct password given),
        // any other string if there is an error.
        output = executeShellCommand("vdc cryptfs restart").trim();

        if (!(output.startsWith("200 ") &&  output.endsWith(" 0"))) {
            CLog.e("restart gave output '%s' while trying to unlock device %s", output,
                    getSerialNumber());
            return false;
        }

        waitForDeviceAvailable();

        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isDeviceEncrypted() throws DeviceNotAvailableException {
        String output = getProperty("ro.crypto.state");

        if (output == null && isEncryptionSupported()) {
            CLog.w("Property ro.crypto.state is null on device %s", getSerialNumber());
        }
        if (output == null) {
            return false;
        }
        return "encrypted".equals(output.trim());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isEncryptionSupported() throws DeviceNotAvailableException {
        if (!isEnableAdbRoot()) {
            CLog.i("root is required for encryption");
            mIsEncryptionSupported = false;
            return mIsEncryptionSupported;
        }
        if (mIsEncryptionSupported != null) {
            return mIsEncryptionSupported.booleanValue();
        }
        enableAdbRoot();

        String output = getProperty("ro.crypto.state");
        if (output == null || "unsupported".equals(output.trim())) {
            mIsEncryptionSupported = false;
            return mIsEncryptionSupported;
        }
        mIsEncryptionSupported = true;
        return mIsEncryptionSupported;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void waitForDeviceOnline(long waitTime) throws DeviceNotAvailableException {
        if (mStateMonitor.waitForDeviceOnline(waitTime) == null) {
            recoverDevice();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void waitForDeviceOnline() throws DeviceNotAvailableException {
        if (mStateMonitor.waitForDeviceOnline() == null) {
            recoverDevice();
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean waitForDeviceAvailable(long waitTime) throws DeviceNotAvailableException {
        if (mStateMonitor.waitForDeviceAvailable(waitTime) == null) {
            return recoverDevice();
        }
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public boolean waitForDeviceAvailable() throws DeviceNotAvailableException {
        if (mStateMonitor.waitForDeviceAvailable() == null) {
            return recoverDevice();
        }
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public boolean waitForDeviceAvailableInRecoverPath(final long waitTime)
            throws DeviceNotAvailableException {
        return mStateMonitor.waitForDeviceAvailableInRecoverPath(waitTime) != null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForDeviceInRecovery(long waitTime) {
        return mStateMonitor.waitForDeviceInRecovery(waitTime);
    }

    /** {@inheritDoc} */
    @Override
    public void waitForDeviceBootloader() throws DeviceNotAvailableException {
        if (mOptions.useUpdatedBootloaderStatus()) {
            CommandResult commandResult =
                    simpleFastbootCommand(
                            mOptions.getFastbootTimeout(),
                            buildFastbootCommand("getvar", "product"));
            if (!CommandStatus.SUCCESS.equals(commandResult.getStatus())) {
                CLog.e(
                        "Waiting for device in bootloader. Status: %s.\nstdout:%s\nstderr:%s",
                        commandResult.getStatus(),
                        commandResult.getStdout(),
                        commandResult.getStderr());
                recoverDeviceFromBootloader();
            } else {
                setDeviceState(TestDeviceState.FASTBOOT);
            }
        } else {
            if (!mStateMonitor.waitForDeviceBootloader(mOptions.getFastbootTimeout())) {
                recoverDeviceFromBootloader();
            }
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean waitForDeviceInSideload(long waitTime) {
        return mStateMonitor.waitForDeviceInSideload(waitTime);
    }

    /**
     * Small helper function to throw an NPE if the passed arg is null.  This should be used when
     * some value will be stored and used later, in which case it'll avoid hard-to-trace
     * asynchronous NullPointerExceptions by throwing the exception synchronously.  This is not
     * intended to be used where the NPE would be thrown synchronously -- just let the jvm take care
     * of it in that case.
     */
    private void throwIfNull(Object obj) {
        if (obj == null) {
            throw new NullPointerException();
        }
    }

    /** Retrieve this device's recovery mechanism. */
    @VisibleForTesting
    IDeviceRecovery getRecovery() {
        return mRecovery;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setRecovery(IDeviceRecovery recovery) {
        throwIfNull(recovery);
        mRecovery = recovery;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setRecoveryMode(RecoveryMode mode) {
        throwIfNull(mRecoveryMode);
        mRecoveryMode = mode;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public RecoveryMode getRecoveryMode() {
        return mRecoveryMode;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setFastbootEnabled(boolean fastbootEnabled) {
        mFastbootEnabled = fastbootEnabled;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isFastbootEnabled() {
        return mFastbootEnabled;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setFastbootPath(String fastbootPath) {
        mFastbootPath = fastbootPath;
        // ensure the device and its associated recovery use the same fastboot version.
        mRecovery.setFastbootPath(fastbootPath);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getFastbootPath() {
        return mFastbootPath;
    }

    /** {@inheritDoc} */
    @Override
    public String getFastbootVersion() {
        try {
            CommandResult res = executeFastbootCommand("--version");
            return res.getStdout().trim();
        } catch (DeviceNotAvailableException e) {
            // Ignored for host side request
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public String getFastbootSerialNumber() {
        if (mFastbootSerialNumber != null) {
            return mFastbootSerialNumber;
        }

        // Only devices which use TCP adb have different fastboot serial number because IPv6
        // link-local address will be used in fastboot mode.
        if (!isAdbTcp()) {
            mFastbootSerialNumber = getSerialNumber();
            CLog.i(
                    "Device %s's fastboot serial number is %s",
                    getSerialNumber(), mFastbootSerialNumber);
            return mFastbootSerialNumber;
        }

        mFastbootSerialNumber = getSerialNumber();
        byte[] macEui48Bytes;

        try {
            boolean adbRoot = isAdbRoot();
            if (!adbRoot) {
                enableAdbRoot();
            }
            macEui48Bytes = getEUI48MacAddressInBytes(ETHERNET_MAC_ADDRESS_COMMAND);
            if (!adbRoot) {
                disableAdbRoot();
            }
        } catch (DeviceNotAvailableException e) {
            CLog.e("Device %s isn't available when get fastboot serial number", getSerialNumber());
            CLog.e(e);
            return getSerialNumber();
        }

        String net_interface = getHostOptions().getNetworkInterface();
        if (net_interface == null || macEui48Bytes == null) {
            CLog.i(
                    "Device %s's fastboot serial number is %s",
                    getSerialNumber(), mFastbootSerialNumber);
            return mFastbootSerialNumber;
        }

        // Create a link-local Inet6Address from the MAC address. The EUI-48 MAC address
        // is converted to an EUI-64 MAC address per RFC 4291. The resulting EUI-64 is
        // used to construct a link-local IPv6 address per RFC 4862.
        byte[] addr = new byte[16];
        addr[0] = (byte) 0xfe;
        addr[1] = (byte) 0x80;
        addr[8] = (byte) (macEui48Bytes[0] ^ (byte) 0x02); // flip the link-local bit
        addr[9] = macEui48Bytes[1];
        addr[10] = macEui48Bytes[2];
        addr[11] = (byte) 0xff;
        addr[12] = (byte) 0xfe;
        addr[13] = macEui48Bytes[3];
        addr[14] = macEui48Bytes[4];
        addr[15] = macEui48Bytes[5];

        try {
            String host_addr = Inet6Address.getByAddress(null, addr, 0).getHostAddress();
            mFastbootSerialNumber = "tcp:" + host_addr.split("%")[0] + "%" + net_interface;
        } catch (UnknownHostException e) {
            CLog.w("Failed to get %s's IPv6 link-local address", getSerialNumber());
            CLog.w(e);
        }

        CLog.i(
                "Device %s's fastboot serial number is %s",
                getSerialNumber(), mFastbootSerialNumber);
        return mFastbootSerialNumber;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDeviceState(final TestDeviceState deviceState) {
        if (!deviceState.equals(getDeviceState())) {
            // disable state changes while fastboot lock is held, because issuing fastboot command
            // will disrupt state
            if (isStateBootloaderOrFastbootd() && mFastbootLock.isLocked()) {
                return;
            }
            mState = deviceState;
            if (!(getIDevice() instanceof StubDevice)) {
                CLog.logAndDisplay(
                        LogLevel.DEBUG,
                        "Device %s state is now %s",
                        getSerialNumber(),
                        deviceState);
            }
            mStateMonitor.setState(deviceState);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TestDeviceState getDeviceState() {
        return mState;
    }

    @Override
    public boolean isAdbTcp() {
        return mStateMonitor.isAdbTcp();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String switchToAdbTcp() throws DeviceNotAvailableException {
        String ipAddress = getIpAddress();
        if (ipAddress == null) {
            CLog.e("connectToTcp failed: Device %s doesn't have an IP", getSerialNumber());
            return null;
        }
        String port = "5555";
        executeAdbCommand("tcpip", port);
        // TODO: analyze result? wait for device offline?
        return String.format("%s:%s", ipAddress, port);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean switchToAdbUsb() throws DeviceNotAvailableException {
        executeAdbCommand("usb");
        // TODO: analyze result? wait for device offline?
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setEmulatorProcess(Process p) {
        mEmulatorProcess = p;

    }

    /**
     * For emulator set {@link SizeLimitedOutputStream} to log output
     * @param output to log the output
     */
    public void setEmulatorOutputStream(SizeLimitedOutputStream output) {
        mEmulatorOutput = output;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stopEmulatorOutput() {
        if (mEmulatorOutput != null) {
            mEmulatorOutput.delete();
            mEmulatorOutput = null;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStreamSource getEmulatorOutput() {
        if (getIDevice().isEmulator()) {
            if (mEmulatorOutput == null) {
                CLog.w("Emulator output for %s was not captured in background",
                        getSerialNumber());
            } else {
                try {
                    return new SnapshotInputStreamSource(
                            "getEmulatorOutput", mEmulatorOutput.getData());
                } catch (IOException e) {
                    CLog.e("Failed to get %s data.", getSerialNumber());
                    CLog.e(e);
                }
            }
        }
        return new ByteArrayInputStreamSource(new byte[0]);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Process getEmulatorProcess() {
        return mEmulatorProcess;
    }

    /**
     * @return <code>true</code> if adb root should be enabled on device
     */
    public boolean isEnableAdbRoot() {
        return mOptions.isEnableAdbRoot();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<String> getInstalledPackageNames() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /** {@inheritDoc} */
    @Override
    public boolean isPackageInstalled(String packageName) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /** {@inheritDoc} */
    @Override
    public boolean isPackageInstalled(String packageName, String userId)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /** {@inheritDoc} */
    @Override
    public Set<ApexInfo> getActiveApexes() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /** {@inheritDoc} */
    @Override
    public List<PackageInfo> getAppPackageInfos() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /** {@inheritDoc} */
    @Override
    public Set<String> getMainlineModuleInfo() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set<String> getUninstallablePackageNames() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PackageInfo getAppPackageInfo(String packageName) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Package's feature");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public TestDeviceOptions getOptions() {
        return mOptions;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getApiLevel() throws DeviceNotAvailableException {
        int apiLevel = UNKNOWN_API_LEVEL;
        try {
            String prop = getProperty(DeviceProperties.SDK_VERSION);
            apiLevel = Integer.parseInt(prop);
        } catch (NumberFormatException nfe) {
            CLog.w(
                    "Unable to get API level from "
                            + DeviceProperties.SDK_VERSION
                            + ", falling back to UNKNOWN.",
                    nfe);
            // ignore, return unknown instead
        }
        return apiLevel;
    }

    /** {@inheritDoc} */
    @Override
    public boolean checkApiLevelAgainstNextRelease(int strictMinLevel)
            throws DeviceNotAvailableException {
        int apiLevel = getApiLevel();
        if (apiLevel > strictMinLevel) {
            return true;
        }
        String codeName = getPropertyWithRecovery(DeviceProperties.BUILD_CODENAME, true);
        if (codeName == null) {
            throw new DeviceRuntimeException(
                    String.format(
                            "Failed to query property '%s'. device returned null.",
                            DeviceProperties.BUILD_CODENAME),
                    DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE);
        }
        codeName = codeName.trim();
        // CUR_DEVELOPMENT_VERSION is the code used by Android for a pre-finalized SDK
        if (strictMinLevel == CUR_DEVELOPMENT_VERSION && !"REL".equals(codeName)) {
            return true;
        }
        apiLevel = apiLevel + ("REL".equals(codeName) ? 0 : 1);
        if (strictMinLevel > apiLevel) {
            return false;
        }
        return true;
    }

    protected int getApiLevelSafe() {
        try {
            return getApiLevel();
        } catch (DeviceNotAvailableException e) {
            CLog.e(e);
            return UNKNOWN_API_LEVEL;
        }
    }

    /** {@inheritDoc} */
    @Override
    public int getLaunchApiLevel() throws DeviceNotAvailableException {
        try {
            String prop = getProperty(DeviceProperties.FIRST_API_LEVEL);
            return Integer.parseInt(prop);
        } catch (NumberFormatException nfe) {
            CLog.w(
                    "Unable to get first launch API level from "
                            + DeviceProperties.FIRST_API_LEVEL
                            + ", falling back to getApiLevel().",
                    nfe);
        }
        return getApiLevel();
    }

    @Override
    public IDeviceStateMonitor getMonitor() {
        return mStateMonitor;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForDeviceShell(long waitTime) {
        return mStateMonitor.waitForDeviceShell(waitTime);
    }

    @Override
    public DeviceAllocationState getAllocationState() {
        return mAllocationState;
    }

    /**
     * {@inheritDoc}
     * <p>
     * Process the DeviceEvent, which may or may not transition this device to a new allocation
     * state.
     * </p>
     */
    @Override
    public DeviceEventResponse handleAllocationEvent(DeviceEvent event) {

        // keep track of whether state has actually changed or not
        boolean stateChanged = false;
        DeviceAllocationState newState;
        DeviceAllocationState oldState = mAllocationState;
        mAllocationStateLock.lock();
        try {
            // update oldState here, just in case in changed before we got lock
            oldState = mAllocationState;
            newState = mAllocationState.handleDeviceEvent(event);
            if (oldState != newState) {
                // state has changed! record this fact, and store the new state
                stateChanged = true;
                mAllocationState = newState;
            }
        } finally {
            mAllocationStateLock.unlock();
        }
        if (stateChanged && mAllocationMonitor != null) {
            // state has changed! Lets inform the allocation monitor listener
            mAllocationMonitor.notifyDeviceStateChange(getSerialNumber(), oldState, newState);
        }
        return new DeviceEventResponse(newState, stateChanged);
    }

    /** {@inheritDoc} */
    @Override
    public long getDeviceTimeOffset(Date date) throws DeviceNotAvailableException {
        long deviceTime = getDeviceDate();

        if (date == null) {
            date = new Date();
        }

        long offset = date.getTime() - deviceTime;
        CLog.d("Time offset = %d ms", offset);
        return offset;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDate(Date date) throws DeviceNotAvailableException {
        if (date == null) {
            date = new Date();
        }
        long timeOffset = getDeviceTimeOffset(date);
        // no need to set date
        if (Math.abs(timeOffset) <= MAX_HOST_DEVICE_TIME_OFFSET) {
            return;
        }
        String dateString = null;
        if (getApiLevel() < 23) {
            // set date in epoch format
            dateString = Long.toString(date.getTime() / 1000); //ms to s
        } else {
            // set date with POSIX like params
            SimpleDateFormat sdf = new java.text.SimpleDateFormat(
                    "MMddHHmmyyyy.ss");
            sdf.setTimeZone(java.util.TimeZone.getTimeZone("UTC"));
            dateString = sdf.format(date);
        }
        // best effort, no verification
        // Use TZ= to default to UTC timezone (b/128353510 for background)
        executeShellCommand("TZ=UTC date -u " + dateString);
    }

    /** {@inheritDoc} */
    @Override
    public long getDeviceDate() throws DeviceNotAvailableException {
        String deviceTimeString = executeShellCommand("date +%s");
        Long deviceTime = null;
        try {
            deviceTime = Long.valueOf(deviceTimeString.trim());
        } catch (NumberFormatException nfe) {
            CLog.i("Invalid device time: \"%s\", ignored.", nfe);
            return 0;
        }
        // Convert from seconds to milliseconds
        return deviceTime * 1000L;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean waitForBootComplete(long timeOut) throws DeviceNotAvailableException {
        return mStateMonitor.waitForBootComplete(timeOut);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ArrayList<Integer> listUsers() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public Map<Integer, UserInfo> getUserInfos() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public int getMaxNumberOfRunningUsersSupported() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isMultiUserSupported() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isHeadlessSystemUserMode() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean canSwitchToHeadlessSystemUser() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isMainUserPermanentAdmin() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public int createUserNoThrow(String name) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int createUser(String name) throws DeviceNotAvailableException, IllegalStateException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int createUser(String name, boolean guest, boolean ephemeral)
            throws DeviceNotAvailableException, IllegalStateException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public int createUser(String name, boolean guest, boolean ephemeral, boolean forTesting)
            throws DeviceNotAvailableException, IllegalStateException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean removeUser(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean startUser(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public boolean startUser(int userId, boolean waitFlag) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean startVisibleBackgroundUser(int userId, int displayId, boolean waitFlag)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean stopUser(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean stopUser(int userId, boolean waitFlag, boolean forceFlag)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isVisibleBackgroundUsersSupported() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isVisibleBackgroundUsersOnDefaultDisplaySupported()
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void remountSystemWritable() throws DeviceNotAvailableException {
        String verity = getProperty("partition.system.verified");
        // have the property set (regardless state) implies verity is enabled, so we send adb
        // command to disable verity
        if (verity != null && !verity.isEmpty()) {
            executeAdbCommand("disable-verity");
            mPropertiesCache.invalidate("partition.system.verified");
            reboot();
        }
        enableAdbRoot();
        executeAdbCommand("remount");
        waitForDeviceAvailable();
    }

    /** {@inheritDoc} */
    @Override
    public void remountVendorWritable() throws DeviceNotAvailableException {
        String verity = getProperty("partition.vendor.verified");
        // have the property set (regardless state) implies verity is enabled, so we send adb
        // command to disable verity
        if (verity != null && !verity.isEmpty()) {
            executeAdbCommand("disable-verity");
            mPropertiesCache.invalidate("partition.vendor.verified");
            reboot();
        }
        enableAdbRoot();
        executeAdbCommand("remount");
        waitForDeviceAvailable();
    }

    /** {@inheritDoc} */
    @Override
    public void remountSystemReadOnly() throws DeviceNotAvailableException {
        String verity = getProperty("partition.system.verified");
        // have the property set (regardless state) implies verity is enabled, so we send adb
        // command to disable verity
        if (verity == null || verity.isEmpty()) {
            executeAdbCommand("enable-verity");
            reboot();
        }
    }

    /** {@inheritDoc} */
    @Override
    public void remountVendorReadOnly() throws DeviceNotAvailableException {
        String verity = getProperty("partition.vendor.verified");
        // have the property set (regardless state) implies verity is enabled, so we send adb
        // command to disable verity
        if (verity == null || verity.isEmpty()) {
            executeAdbCommand("enable-verity");
            reboot();
        }
    }

    /** {@inheritDoc} */
    @Override
    public Integer getPrimaryUserId() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public Integer getMainUserId() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** Used internally to fallback to non-user logic */
    private int getCurrentUserCompatible() throws DeviceNotAvailableException {
        try {
            return getCurrentUser();
        } catch (RuntimeException e) {
            return 0;
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getCurrentUser() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isUserVisible(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    @Override
    public boolean isUserVisibleOnDisplay(int userId, int displayId)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public boolean isUserSecondary(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }


    /**
     * {@inheritDoc}
     */
    @Override
    public int getUserFlags(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getUserSerialNumber(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean switchUser(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean switchUser(int userId, long timeout) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isUserRunning(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean hasFeature(String feature) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support pm's features.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSetting(String namespace, String key)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for setting's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getSetting(int userId, String namespace, String key)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for setting's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public Map<String, String> getAllSettings(String namespace) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for setting's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSetting(String namespace, String key, String value)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for setting's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setSetting(int userId, String namespace, String key, String value)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for setting's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getBuildSigningKeys() throws DeviceNotAvailableException {
        String buildTags = getProperty(DeviceProperties.BUILD_TAGS);
        if (buildTags != null) {
            String[] tags = buildTags.split(",");
            for (String tag : tags) {
                Matcher m = KEYS_PATTERN.matcher(tag);
                if (m.matches()) {
                    return tag;
                }
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getAndroidId(int userId) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Map<Integer, String> getAndroidIds() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public boolean setDeviceOwner(String componentName, int userId)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public boolean removeAdmin(String componentName, int userId)
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public void removeOwners() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void disableKeyguard() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for Window Manager's features");
    }

    /** {@inheritDoc} */
    @Override
    public String getDeviceClass() {
        IDevice device = getIDevice();
        if (device == null) {
            CLog.w("No IDevice instance, cannot determine device class.");
            return "";
        }
        return device.getClass().getSimpleName();
    }

    /** {@inheritDoc} */
    @Override
    public void preInvocationSetup(IBuildInfo info, MultiMap<String, String> attributes)
            throws TargetSetupError, DeviceNotAvailableException {
        // Default implementation
        mContentProvider = null;
        mShouldSkipContentProviderSetup = false;
        try {
            mExecuteShellCommandLogs =
                    FileUtil.createTempFile("TestDevice_ExecuteShellCommands", ".txt");
        } catch (IOException e) {
            throw new TargetSetupError(
                    "Failed to create the executeShellCommand log file.",
                    e,
                    getDeviceDescriptor(),
                    InfraErrorIdentifier.FAIL_TO_CREATE_FILE);
        }
        initializeConnection(info, attributes);
    }

    protected void initializeConnection(IBuildInfo info, MultiMap<String, String> attributes)
            throws DeviceNotAvailableException, TargetSetupError {
        try (CloseableTraceScope ignored = new CloseableTraceScope("initializeConnection")) {
            ConnectionBuilder builder =
                    new ConnectionBuilder(getRunUtil(), this, info, getLogger());
            if (attributes != null) {
                builder.addAttributes(attributes);
            }
            addExtraConnectionBuilderArgs(builder);
            mConnection = DefaultConnection.createConnection(builder);
            CLog.d("Using connection: %s (%s)", mConnection, getIDevice());
            mConnection.initializeConnection();
        }
    }

    protected void addExtraConnectionBuilderArgs(ConnectionBuilder builder) {
        if (mConnectionAvd != null) {
            builder.setExistingAvdInfo(mConnectionAvd);
        }
    }

    public final void setConnectionAvdInfo(GceAvdInfo avdInfo) {
        mConnectionAvd = avdInfo;
    }

    /** {@inheritDoc} */
    @Override
    public void postInvocationTearDown(Throwable exception) {
        invalidatePropertyCache();
        mConfiguration = null;
        mIsEncryptionSupported = null;
        FileUtil.deleteFile(mExecuteShellCommandLogs);
        mExecuteShellCommandLogs = null;
        FileUtil.recursiveDelete(mUnpackedFastbootDir);
        getConnection().tearDownConnection();
        mConnectionAvd = null;
        mDeviceActionReceivers.clear();
        // Default implementation
        if (getIDevice() instanceof StubDevice) {
            return;
        }
        // Reset the Content Provider bit.
        mShouldSkipContentProviderSetup = false;
        try {
            // If we never installed it, don't even bother checking for it during tear down.
            if (mContentProvider == null) {
                return;
            }
            if (exception instanceof DeviceNotAvailableException) {
                CLog.e(
                        "Skip Tradefed Content Provider teardown due to"
                                + " DeviceNotAvailableException.");
                return;
            }
            if (TestDeviceState.ONLINE.equals(getDeviceState())) {
                mContentProvider.tearDown();
            }
        } catch (DeviceNotAvailableException e) {
            CLog.e(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isHeadless() throws DeviceNotAvailableException {
        if (getProperty(DeviceProperties.BUILD_HEADLESS) != null) {
            return true;
        }
        return false;
    }

    protected void checkApiLevelAgainst(String feature, int strictMinLevel) {
        try {
            if (getApiLevel() < strictMinLevel){
                throw new HarnessRuntimeException(
                        String.format(
                                "%s not supported on %s. " + "Must be API %d.",
                                feature, getSerialNumber(), strictMinLevel),
                        DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE);
            }
        } catch (DeviceNotAvailableException e) {
            throw new HarnessRuntimeException(
                    "Device became unavailable while checking API level",
                    e,
                    DeviceErrorIdentifier.DEVICE_UNAVAILABLE);
        }
    }

    @Override
    public DeviceDescriptor getCachedDeviceDescriptor() {
        return getCachedDeviceDescriptor(false);
    }

    /** {@inheritDoc} */
    @Override
    public DeviceDescriptor getCachedDeviceDescriptor(boolean shortDescriptor) {
        synchronized (mCacheLock) {
            if (DeviceAllocationState.Allocated.equals(getAllocationState())) {
                if (mCachedDeviceDescriptor == null) {
                    // Create the cache the very first time when it's allocated.
                    mCachedDeviceDescriptor = getDeviceDescriptor(false);
                    return mCachedDeviceDescriptor;
                }
                return mCachedDeviceDescriptor;
            }
            // If device is not allocated, just return current information
            mCachedDeviceDescriptor = null;
            return getDeviceDescriptor(shortDescriptor);
        }
    }

    @Override
    public DeviceDescriptor getDeviceDescriptor() {
        return getDeviceDescriptor(false);
    }

    /** {@inheritDoc} */
    @Override
    public DeviceDescriptor getDeviceDescriptor(boolean shortDescriptor) {
        IDeviceSelection selector = new DeviceSelectionOptions();
        IDevice idevice = getIDevice();
        try {
            boolean isTemporary = false;
            if (idevice instanceof NullDevice) {
                isTemporary = ((NullDevice) idevice).isTemporary();
            }
            if (shortDescriptor) {
                // Return only info that do not require device inspection
                return new DeviceDescriptor(
                        idevice.getSerialNumber(),
                        null,
                        idevice instanceof StubDevice,
                        idevice.getState(),
                        getAllocationState(),
                        getDeviceState(),
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        getDeviceClass(),
                        null,
                        null,
                        null,
                        isTemporary,
                        null,
                        null,
                        idevice);
            }
            // All the operations to create the descriptor need to be safe (should not trigger any
            // device side effects like recovery)
            String sdkVersion = null;
            String buildAlias = null;
            String hardwareRev = null;
            if (TestDeviceState.ONLINE.equals(getDeviceState())) {
                sdkVersion = getPropertyWithRecovery(DeviceProperties.SDK_VERSION, false);
                buildAlias = getPropertyWithRecovery(DeviceProperties.BUILD_ALIAS, false);
                hardwareRev = getPropertyWithRecovery(DeviceProperties.HARDWARE_REVISION, false);
            }
            return new DeviceDescriptor(
                    idevice.getSerialNumber(),
                    null,
                    idevice instanceof StubDevice,
                    idevice.getState(),
                    getAllocationState(),
                    getDeviceState(),
                    getDisplayString(selector.getDeviceProductType(idevice)),
                    getDisplayString(selector.getDeviceProductVariant(idevice)),
                    getDisplayString(sdkVersion),
                    getDisplayString(buildAlias),
                    getDisplayString(hardwareRev),
                    getDisplayString(getBattery()),
                    getDeviceClass(),
                    getDisplayString(getMacAddress()),
                    getDisplayString(getSimState()),
                    getDisplayString(getSimOperator()),
                    isTemporary,
                    null,
                    null,
                    idevice);
        } catch (RuntimeException|DeviceNotAvailableException e) {
            CLog.e("Exception while building device '%s' description:", getSerialNumber());
            CLog.e(e);
        }
        return null;
    }

    /**
     * Return the displayable string for given object
     */
    private String getDisplayString(Object o) {
        return o == null ? "unknown" : o.toString();
    }

    /** {@inheritDoc} */
    @Override
    public ProcessInfo getProcessByName(String processName) throws DeviceNotAvailableException {
        String pidString = getProcessPid(processName);
        if (pidString == null) {
            return null;
        }
        long startTime = getProcessStartTimeByPid(pidString);
        if (startTime == -1L) {
            return null;
        }
        return new ProcessInfo(
                getProcessUserByPid(pidString),
                Integer.parseInt(pidString),
                processName,
                startTime);
    }

    /** Return the process start time since epoch for the given pid string */
    private long getProcessStartTimeByPid(String pidString) throws DeviceNotAvailableException {
        String output = executeShellCommand(String.format("ps -p %s -o stime=", pidString));
        if (output != null && !output.trim().isEmpty()) {
            output = output.trim();

            String dateInSeconds;

            // On API 28 and lower, there is a bug in toybox that prevents date from parsing
            // timestamps containing a space, e.g. -D"%Y-%m-%d %H:%M:%S" cannot be used to parse
            // the stime:19 output from ps. Instead, we'll reconstruct the timestamp.
            if (getApiLevel() <= 28) {
                dateInSeconds =
                        executeShellCommand(
                                "date -d \"$(date +%Y:%m:%d):"
                                        + output
                                        + "\" +%s -D \"%Y:%m:%d:%H:%M:%S\"");
            } else {
                dateInSeconds = executeShellCommand("date -d\"" + output + "\" +%s");
            }
            if (Strings.isNullOrEmpty(dateInSeconds)) {
                return -1L;
            }
            try {
                return Long.parseLong(dateInSeconds.trim());
            } catch (NumberFormatException e) {
                CLog.e("Failed to parse the start time for process:");
                CLog.e(e);
                return -1L;
            }
        }
        return -1L;
    }

    /** Return the process user for the given pid string */
    private String getProcessUserByPid(String pidString) throws DeviceNotAvailableException {
        String output = executeShellCommand("stat -c%U /proc/" + pidString);
        if (output != null && !output.trim().isEmpty()) {
            try {
                return output.trim();
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Map<Long, String> getBootHistory() throws DeviceNotAvailableException {
        String output = getProperty(DeviceProperties.BOOT_REASON_HISTORY);
        /* Sample output:
        kernel_panic,1556587278
        reboot,,1556238008
        reboot,,1556237796
        reboot,,1556237725
        */
        Map<Long, String> bootHistory = new LinkedHashMap<Long, String>();
        if (Strings.isNullOrEmpty(output)) {
            return bootHistory;
        }
        for (String line : output.split("\\n")) {
            String infoStr[] = line.split(",");
            String startStr = infoStr[infoStr.length - 1];
            try {
                long startTime = Long.parseLong(startStr.trim());
                bootHistory.put(startTime, infoStr[0].trim());
            } catch (NumberFormatException e) {
                CLog.e("Fail to parse boot time from line %s", line);
            }
        }
        return bootHistory;
    }

    /** {@inheritDoc} */
    @Override
    public Map<Long, String> getBootHistorySince(long utcEpochTime, TimeUnit timeUnit)
            throws DeviceNotAvailableException {
        long utcEpochTimeSec = TimeUnit.SECONDS.convert(utcEpochTime, timeUnit);
        Map<Long, String> bootHistory = new LinkedHashMap<Long, String>();
        for (Map.Entry<Long, String> entry : getBootHistory().entrySet()) {
            if (entry.getKey() >= utcEpochTimeSec) {
                bootHistory.put(entry.getKey(), entry.getValue());
            }
        }
        return bootHistory;
    }

    private boolean hasNormalRebootSince(long utcEpochTime, TimeUnit timeUnit)
            throws DeviceNotAvailableException {
        Map<Long, String> bootHistory = getBootHistorySince(utcEpochTime, timeUnit);
        if (bootHistory.isEmpty()) {
            CLog.w("There is no reboot history since %s", utcEpochTime);
            return false;
        }

        CLog.i(
                "There are new boot history since %d. NewBootHistory = %s",
                utcEpochTime, bootHistory);
        // Check if there is reboot reason other than "reboot".
        // Raise RuntimeException if there is abnormal reboot.
        for (Map.Entry<Long, String> entry : bootHistory.entrySet()) {
            if (!"reboot".equals(entry.getValue())) {
                throw new HarnessRuntimeException(
                        String.format(
                                "Device %s has abnormal reboot reason %s at %d",
                                getSerialNumber(), entry.getValue(), entry.getKey()),
                        DeviceErrorIdentifier.UNEXPECTED_REBOOT);
            }
        }
        return true;
    }

    /**
     * Check current system process is restarted after last reboot
     *
     * @param systemServerProcess the system_server {@link ProcessInfo}
     * @return true if system_server process restarted after last reboot; false if not
     * @throws DeviceNotAvailableException
     */
    private boolean checkSystemProcessRestartedAfterLastReboot(ProcessInfo systemServerProcess)
            throws DeviceNotAvailableException {
        // If time gap from last reboot to current system_server process start time is more than
        // MAX_SYSTEM_SERVER_DELAY_AFTER_BOOT_UP seconds, we conclude the system_server restarted
        // after boot up.
        if (!hasNormalRebootSince(
                systemServerProcess.getStartTime() - MAX_SYSTEM_SERVER_DELAY_AFTER_BOOT_UP_SEC,
                TimeUnit.SECONDS)) {
            CLog.i(
                    "Device last reboot is more than %s seconds away from current system_server "
                            + "process start time. The system_server process restarted after "
                            + "last boot up",
                    MAX_SYSTEM_SERVER_DELAY_AFTER_BOOT_UP_SEC);
            return true;
        } else {
            // Current system_server start within MAX_SYSTEM_SERVER_DELAY_AFTER_BOOT_UP
            // seconds after device last boot up
            return false;
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean deviceSoftRestartedSince(long utcEpochTime, TimeUnit timeUnit)
            throws DeviceNotAvailableException {
        ProcessInfo currSystemServerProcess = getProcessByName("system_server");
        if (currSystemServerProcess == null) {
            CLog.i("The system_server process is not available on the device.");
            return true;
        }

        // The system_server process started at or before utcEpochTime, there is no soft-restart
        if (Math.abs(
                        currSystemServerProcess.getStartTime()
                                - TimeUnit.SECONDS.convert(utcEpochTime, timeUnit))
                <= 1) {
            return false;
        }

        // The system_server process restarted after device utcEpochTime in second.
        // Check if there is new reboot history, if no new reboot, device soft-restarted.
        // If there is no normal reboot, soft-restart is detected.
        if (!hasNormalRebootSince(utcEpochTime, timeUnit)) {
            return true;
        }

        // There is new reboot since utcEpochTime. Check if system_server restarted after boot up.
        return checkSystemProcessRestartedAfterLastReboot(currSystemServerProcess);
    }

    /** {@inheritDoc} */
    @Override
    public boolean deviceSoftRestarted(ProcessInfo prevSystemServerProcess)
            throws DeviceNotAvailableException {
        if (prevSystemServerProcess == null) {
            CLog.i("The given system_server process is null. Abort deviceSoftRestarted check.");
            return false;
        }
        ProcessInfo currSystemServerProcess = getProcessByName("system_server");
        if (currSystemServerProcess == null) {
            CLog.i("The system_server process is not available on the device.");
            return true;
        }

        // Compare the start time with a 1 seconds accuracy due to how the date is computed
        if (currSystemServerProcess.getPid() == prevSystemServerProcess.getPid()
                && Math.abs(
                                currSystemServerProcess.getStartTime()
                                        - prevSystemServerProcess.getStartTime())
                        <= 1) {
            return false;
        }

        CLog.v(
                "current system_server: %s; prev system_server: %s",
                currSystemServerProcess, prevSystemServerProcess);

        // The system_server process restarted.
        // Check boot history with previous system_server start time.
        // If there is no normal reboot, soft-restart is detected
        if (!hasNormalRebootSince(prevSystemServerProcess.getStartTime(), TimeUnit.SECONDS)) {
            return true;
        }

        // There is reboot since prevSystemServerProcess.getStartTime().
        // Check if system_server restarted after boot up.
        return checkSystemProcessRestartedAfterLastReboot(currSystemServerProcess);

    }

    /**
     * Validates that the given input is a valid MAC address
     *
     * @param address input to validate
     * @return true if the input is a valid MAC address
     */
    boolean isMacAddress(String address) {
        Pattern macPattern = Pattern.compile(MAC_ADDRESS_PATTERN);
        Matcher macMatcher = macPattern.matcher(address);
        return macMatcher.find();
    }

    /**
     * Query Mac address from the device
     *
     * @param command the query command
     * @return the MAC address of the device, null if it fails to query from the device
     */
    private String getMacAddress(String command) {
        if (getIDevice() instanceof StubDevice) {
            // Do not query MAC addresses from stub devices.
            return null;
        }
        if (!TestDeviceState.ONLINE.equals(mState)) {
            // Only query MAC addresses from online devices.
            return null;
        }
        CollectingOutputReceiver receiver = new CollectingOutputReceiver();
        try {
            mIDevice.executeShellCommand(command, receiver);
        } catch (IOException | TimeoutException | AdbCommandRejectedException |
                ShellCommandUnresponsiveException e) {
            CLog.w(
                    "Failed to query MAC address for %s by '%s'",
                    mIDevice.getSerialNumber(), command);
            CLog.w(e);
        }
        String output = receiver.getOutput().trim();
        if (isMacAddress(output)) {
            return output;
        }
        CLog.d(
                "No valid MAC address queried from device %s by '%s'",
                mIDevice.getSerialNumber(), command);
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public String getMacAddress() {
        return getMacAddress(MAC_ADDRESS_COMMAND);
    }

    /**
     * Query EUI-48 MAC address from the device
     *
     * @param command the query command
     * @return the EUI-48 MAC address in long, 0 if it fails to query from the device
     * @throws IllegalArgumentException
     */
    long getEUI48MacAddressInLong(String command) {
        String addr = getMacAddress(command);
        if (addr == null) {
            return 0;
        }

        String[] parts = addr.split(":");
        if (parts.length != ETHER_ADDR_LEN) {
            throw new IllegalArgumentException(addr + " was not a valid MAC address");
        }
        long longAddr = 0;
        for (int i = 0; i < parts.length; i++) {
            int x = Integer.valueOf(parts[i], 16);
            if (x < 0 || 0xff < x) {
                throw new IllegalArgumentException(addr + "was not a valid MAC address");
            }
            longAddr = x + (longAddr << 8);
        }

        return longAddr;
    }

    /**
     * Query EUI-48 MAC address from the device
     *
     * @param command the query command
     * @return the EUI-48 MAC address in byte[], null if it fails to query from the device
     * @throws IllegalArgumentException
     */
    byte[] getEUI48MacAddressInBytes(String command) {
        long addr = getEUI48MacAddressInLong(command);
        if (addr == 0) {
            return null;
        }

        byte[] bytes = new byte[ETHER_ADDR_LEN];
        int index = ETHER_ADDR_LEN;
        while (index-- > 0) {
            bytes[index] = (byte) addr;
            addr = addr >> 8;
        }
        return bytes;
    }

    /** {@inheritDoc} */
    @Override
    public String getSimState() {
        if (getIDevice() instanceof StubDevice) {
            // Do not query SIM state from stub devices.
            return null;
        }
        if (!TestDeviceState.ONLINE.equals(mState)) {
            // Only query SIM state from online devices.
            return null;
        }
        try {
            return getPropertyWithRecovery(SIM_STATE_PROP, false);
        } catch (DeviceNotAvailableException dnae) {
            CLog.w("DeviceNotAvailableException while fetching SIM state");
            return null;
        }
    }

    /** {@inheritDoc} */
    @Override
    public String getSimOperator() {
        if (getIDevice() instanceof StubDevice) {
            // Do not query SIM operator from stub devices.
            return null;
        }
        if (!TestDeviceState.ONLINE.equals(mState)) {
            // Only query SIM operator from online devices.
            return null;
        }
        try {
            return getPropertyWithRecovery(SIM_OPERATOR_PROP, false);
        } catch (DeviceNotAvailableException dnae) {
            CLog.w("DeviceNotAvailableException while fetching SIM operator");
            return null;
        }
    }

    /** {@inheritDoc} */
    @Override
    public File dumpHeap(String process, String devicePath) throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("dumpHeap is not supported.");
    }

    /** {@inheritDoc} */
    @Override
    public String getProcessPid(String process) throws DeviceNotAvailableException {
        String output = executeShellCommand(String.format("pidof %s", process)).trim();
        if (checkValidPid(output)) {
            return output;
        }
        CLog.e("Failed to find a valid pid for process '%s'.", process);
        return null;
    }

    /** {@inheritDoc} */
    @Override
    @FormatMethod
    public void logOnDevice(String tag, LogLevel level, String format, Object... args) {
        String message = String.format(format, args);
        try {
            String levelLetter = logLevelToLogcatLevel(level);
            String command = String.format("log -t %s -p %s '%s'", tag, levelLetter, message);
            executeShellCommand(command);
        } catch (DeviceNotAvailableException e) {
            CLog.e("Device went not available when attempting to log '%s'", message);
            CLog.e(e);
        }
    }

    /** Convert the {@link LogLevel} to the letter used in log (see 'adb shell log --help'). */
    private String logLevelToLogcatLevel(LogLevel level) {
        switch (level) {
            case DEBUG:
                return "d";
            case ERROR:
                return "e";
            case INFO:
                return "i";
            case VERBOSE:
                return "v";
            case WARN:
                return "w";
            default:
                return "i";
        }
    }

    /** {@inheritDoc} */
    @Override
    public long getTotalMemory() {
        // "/proc/meminfo" always returns value in kilobytes.
        long totalMemory = 0;
        String output = null;
        try {
            output = executeShellCommand("cat /proc/meminfo | grep MemTotal");
        } catch (DeviceNotAvailableException e) {
            CLog.e(e);
            return -1;
        }
        if (output.isEmpty()) {
            return -1;
        }
        String[] results = output.split("\\s+");
        try {
            totalMemory = Long.parseLong(results[1].replaceAll("\\D+", ""));
        } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
            CLog.e(e);
            return -1;
        }
        return totalMemory * 1024;
    }

    /** {@inheritDoc} */
    @Override
    public Integer getBattery() {
        if (getIDevice() instanceof StubDevice) {
            return null;
        }
        if (isStateBootloaderOrFastbootd()) {
            return null;
        }
        try {
            // Use default 5 minutes freshness
            Future<Integer> batteryFuture = getIDevice().getBattery();
            // Get cached value or wait up to 500ms for battery level query
            return batteryFuture.get(500, TimeUnit.MILLISECONDS);
        } catch (InterruptedException
                | ExecutionException
                | java.util.concurrent.TimeoutException e) {
            CLog.w(
                    "Failed to query battery level for %s: %s",
                    getIDevice().getSerialNumber(), e.toString());
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public Set<Long> listDisplayIds() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("dumpsys SurfaceFlinger is not supported.");
    }

    @Override
    public Set<Integer> listDisplayIdsForStartingVisibleBackgroundUsers()
            throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for user's feature.");
    }

    /** {@inheritDoc} */
    @Override
    public long getLastExpectedRebootTimeMillis() {
        return mLastTradefedRebootTime;
    }

    /** {@inheritDoc} */
    @Override
    public List<File> getTombstones() throws DeviceNotAvailableException {
        List<File> tombstones = new ArrayList<>();
        if (!isAdbRoot()) {
            CLog.w("Device was not root, cannot collect tombstones.");
            return tombstones;
        }
        for (String tombName : getChildren(TOMBSTONE_PATH)) {
            File tombFile = pullFile(TOMBSTONE_PATH + tombName);
            if (tombFile != null) {
                tombstones.add(tombFile);
            }
        }
        return tombstones;
    }

    @Override
    public Set<DeviceFoldableState> getFoldableStates() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for foldable states.");
    }

    @Override
    public DeviceFoldableState getCurrentFoldableState() throws DeviceNotAvailableException {
        throw new UnsupportedOperationException("No support for foldable states.");
    }

    /** Validate that pid is an integer and not empty. */
    private boolean checkValidPid(String output) {
        if (output.isEmpty()) {
            return false;
        }
        try {
            Integer.parseInt(output);
        } catch (NumberFormatException e) {
            CLog.e(e);
            return false;
        }
        return true;
    }

    /** Gets the {@link IHostOptions} instance to use. */
    @VisibleForTesting
    IHostOptions getHostOptions() {
        return GlobalConfiguration.getInstance().getHostOptions();
    }

    /** Returns the {@link ContentProviderHandler} or null if not available. */
    @VisibleForTesting
    ContentProviderHandler getContentProvider() throws DeviceNotAvailableException {
        // If disabled at the device level, don't attempt any checks.
        if (!getOptions().shouldUseContentProvider()) {
            return null;
        }
        // Prevent usage of content provider before API 28 as it would not work well since content
        // tool is not working before P.
        if (getApiLevel() < 28) {
            return null;
        }
        if (mContentProvider == null) {
            mContentProvider = new ContentProviderHandler(this);
        }
        // Force the install if we saw an error with content provider installation.
        if (mContentProvider.contentProviderNotFound()) {
            mShouldSkipContentProviderSetup = false;
        }
        if (!mShouldSkipContentProviderSetup) {
            boolean res = mContentProvider.setUp();
            if (!res) {
                // TODO: once CP becomes a requirement, throw/fail the test if CP can't be found
                return null;
            }
            mShouldSkipContentProviderSetup = true;
        }
        return mContentProvider;
    }

    /** Reset the flag for content provider setup in order to trigger it again. */
    public void resetContentProviderSetup() {
        mShouldSkipContentProviderSetup = false;
    }

    /** The log that contains all the {@link #executeShellCommand(String)} logs. */
    public final File getExecuteShellCommandLog() {
        return mExecuteShellCommandLogs;
    }

    /** Executes a simple fastboot command and report the status of the command. */
    @VisibleForTesting
    protected CommandResult simpleFastbootCommand(final long timeout, String[] fullCmd)
            throws UnsupportedOperationException {
        return simpleFastbootCommand(timeout, new HashMap<>(), fullCmd);
    }

    /**
     * Executes a simple fastboot command with environment variables and report the status of the
     * command.
     */
    @VisibleForTesting
    protected CommandResult simpleFastbootCommand(
            final long timeout, Map<String, String> envVarMap, String[] fullCmd)
            throws UnsupportedOperationException {
        if (!mFastbootEnabled) {
            throw new UnsupportedOperationException(
                    String.format(
                            "Attempted to fastboot on device %s , but fastboot "
                                    + "is disabled. Aborting.",
                            getSerialNumber()));
        }
        IRunUtil runUtil;
        if (!envVarMap.isEmpty()) {
            runUtil = new RunUtil();
        } else {
            runUtil = getRunUtil();
        }
        for (Map.Entry<String, String> entry : envVarMap.entrySet()) {
            CLog.v(
                    String.format(
                            "Set environment variable %s to %s", entry.getKey(), entry.getValue()));
            runUtil.setEnvVariable(entry.getKey(), entry.getValue());
        }
        CommandResult result = new CommandResult(CommandStatus.EXCEPTION);
        // block state changes while executing a fastboot command, since
        // device will disappear from fastboot devices while command is being executed
        mFastbootLock.lock();
        try {
            if (mOptions.getFastbootOutputTimeout() > 0) {
                result =
                        runUtil.runTimedCmdWithOutputMonitor(
                                timeout, mOptions.getFastbootOutputTimeout(), fullCmd);
            } else {
                result = runUtil.runTimedCmd(timeout, fullCmd);
            }
        } finally {
            mFastbootLock.unlock();
        }
        return result;
    }

    /** The current connection associated with the device. */
    @Override
    public AbstractConnection getConnection() {
        if (mConnection == null) {
            mConnection =
                    DefaultConnection.createInopConnection(
                            new ConnectionBuilder(getRunUtil(), this, null, getLogger()));
        }
        return mConnection;
    }

    /** Check if debugfs is mounted. */
    @Override
    public boolean isDebugfsMounted() throws DeviceNotAvailableException {
        return CommandStatus.SUCCESS.equals(
                executeShellV2Command(CHECK_DEBUGFS_MNT_COMMAND).getStatus());
    }

    /** Mount debugfs. */
    @Override
    public void mountDebugfs() throws DeviceNotAvailableException {
        if (isDebugfsMounted()) {
            CLog.w("debugfs already mounted.");
            return;
        }

        CommandResult result = executeShellV2Command(MOUNT_DEBUGFS_COMMAND);
        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
            CLog.e("Failed to mount debugfs. %s", result);
            throw new DeviceRuntimeException(
                    "'" + MOUNT_DEBUGFS_COMMAND + "' has failed: " + result,
                    DeviceErrorIdentifier.SHELL_COMMAND_ERROR);
        }
    }

    /** Unmount debugfs. */
    @Override
    public void unmountDebugfs() throws DeviceNotAvailableException {
        if (!isDebugfsMounted()) {
            CLog.w("debugfs not mounted to unmount.");
            return;
        }

        CommandResult result = executeShellV2Command(UNMOUNT_DEBUGFS_COMMAND);
        if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
            CLog.e("Failed to unmount debugfs. %s", result);
            throw new DeviceRuntimeException(
                    "'" + UNMOUNT_DEBUGFS_COMMAND + "' has failed: " + result,
                    DeviceErrorIdentifier.SHELL_COMMAND_ERROR);
        }
    }

    /**
     * Notifies all {@link IDeviceActionReceiver} about reboot start event.
     *
     * @throws DeviceNotAvailableException
     */
    protected void notifyRebootStarted() throws DeviceNotAvailableException {
        try (CloseableTraceScope ignored = new CloseableTraceScope("rebootStartedCallbacks")) {
            for (IDeviceActionReceiver dar : mDeviceActionReceivers) {
                try {
                    inRebootCallback = true;
                    dar.rebootStarted(this);
                } catch (DeviceNotAvailableException dnae) {
                    inRebootCallback = false;
                    throw dnae;
                } catch (Exception e) {
                    logDeviceActionException("notifyRebootStarted", e, true);
                } finally {
                    inRebootCallback = false;
                }
            }
        }
    }

    /**
     * Notifies all {@link IDeviceActionReceiver} about reboot end event.
     *
     * @throws DeviceNotAvailableException
     */
    protected void notifyRebootEnded() throws DeviceNotAvailableException {
        try (CloseableTraceScope ignored = new CloseableTraceScope("rebootEndedCallbacks")) {
            for (IDeviceActionReceiver dar : mDeviceActionReceivers) {
                try {
                    inRebootCallback = true;
                    dar.rebootEnded(this);
                } catch (DeviceNotAvailableException dnae) {
                    inRebootCallback = false;
                    throw dnae;
                } catch (Exception e) {
                    logDeviceActionException("notifyRebootEnded", e, true);
                } finally {
                    inRebootCallback = false;
                }
            }
        }
    }

    /**
     * Returns whether reboot callbacks is currently being executed or not. All public api's for
     * reboot should be disabled if true.
     */
    protected boolean isInRebootCallback() {
        return inRebootCallback;
    }

    @Override
    public void setTestLogger(ITestLogger testLogger) {
        mTestLogger = testLogger;
    }

    protected ITestLogger getLogger() {
        return mTestLogger;
    }

    /**
     * Marks the TestDevice as microdroid and sets its CID.
     *
     * @param process Process of the Microdroid VM.
     */
    protected void setMicrodroidProcess(Process process) {
        mMicrodroidProcess = process;
    }

    /**
     * @return Returns the Process of the Microdroid VM. If TestDevice is not a Microdroid, returns
     *     null.
     */
    public Process getMicrodroidProcess() {
        return mMicrodroidProcess;
    }

    protected void setTestDeviceOptions(Map<String, String> deviceOptions) {
        try {
            OptionSetter setter = new OptionSetter(this.getOptions());
            for (Map.Entry<String, String> optionsKeyValue : deviceOptions.entrySet()) {
                setter.setOptionValue(optionsKeyValue.getKey(), optionsKeyValue.getValue());
            }
        } catch (ConfigurationException e) {
            CLog.w(e);
        }
    }

    public void invalidatePropertyCache() {
        mPropertiesCache.invalidateAll();
    }
}
