# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

import logging
import re
import os
import shutil
import tempfile
import time
import traceback

from devicemanager import DeviceManager, DMError
from mozprocess import ProcessHandler
import mozfile


class DeviceManagerADB(DeviceManager):
    """
    Implementation of DeviceManager interface that uses the Android "adb"
    utility to communicate with the device. Normally used to communicate
    with a device that is directly connected with the host machine over a USB
    port.
    """

    _haveRootShell = None
    _haveSu = None
    _suModifier = None
    _lsModifier = None
    _useZip = False
    _logcatNeedsRoot = False
    _pollingInterval = 0.01
    _packageName = None
    _tempDir = None
    connected = False

    def __init__(self, host=None, port=5555, retryLimit=5, packageName='fennec',
                 adbPath='adb', deviceSerial=None, deviceRoot=None,
                 logLevel=logging.ERROR, autoconnect=True, runAdbAsRoot=False,
                 serverHost=None, serverPort=None, **kwargs):
        DeviceManager.__init__(self, logLevel=logLevel,
                               deviceRoot=deviceRoot)
        self.host = host
        self.port = port
        self.retryLimit = retryLimit

        self._serverHost = serverHost
        self._serverPort = serverPort

        # the path to adb, or 'adb' to assume that it's on the PATH
        self._adbPath = adbPath

        # The serial number of the device to use with adb, used in cases
        # where multiple devices are being managed by the same adb instance.
        self._deviceSerial = deviceSerial

        # Some devices do no start adb as root, if allowed you can use
        # this to reboot adbd on the device as root automatically
        self._runAdbAsRoot = runAdbAsRoot

        if packageName == 'fennec':
            if os.getenv('USER'):
                self._packageName = 'org.mozilla.fennec_' + os.getenv('USER')
            else:
                self._packageName = 'org.mozilla.fennec_'
        elif packageName:
            self._packageName = packageName

        # verify that we can run the adb command. can't continue otherwise
        self._verifyADB()

        if autoconnect:
            self.connect()

    def connect(self):
        if not self.connected:
            # try to connect to the device over tcp/ip if we have a hostname
            if self.host:
                self._connectRemoteADB()

            # verify that we can connect to the device. can't continue
            self._verifyDevice()

            # Some commands require root to work properly, even with ADB (e.g.
            # grabbing APKs out of /data). For these cases, we check whether
            # we're running as root. If that isn't true, check for the
            # existence of an su binary
            self._checkForRoot()

            # can we use zip to speed up some file operations? (currently not
            # required)
            try:
                self._verifyZip()
            except DMError:
                pass

    def __del__(self):
        if self.host:
            self._disconnectRemoteADB()

    def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False):
        # FIXME: this function buffers all output of the command into memory,
        # always. :(

        # If requested to run as root, check that we can actually do that
        if root:
            if self._haveRootShell is None and self._haveSu is None:
                self._checkForRoot()
            if not self._haveRootShell and not self._haveSu:
                raise DMError(
                    "Shell command '%s' requested to run as root but root "
                    "is not available on this device. Root your device or "
                    "refactor the test/harness to not require root." %
                    self._escapedCommandLine(cmd))

        # Getting the return code is more complex than you'd think because adb
        # doesn't actually return the return code from a process, so we have to
        # capture the output to get it
        if root and self._haveSu:
            cmdline = "su %s \"%s\"" % (self._suModifier,
                                        self._escapedCommandLine(cmd))
        else:
            cmdline = self._escapedCommandLine(cmd)
        cmdline += "; echo $?"

        # prepend cwd and env to command if necessary
        if cwd:
            cmdline = "cd %s; %s" % (cwd, cmdline)
        if env:
            envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
            cmdline = envstr + "; " + cmdline

        # all output should be in stdout
        args=[self._adbPath]
        if self._serverHost is not None:
            args.extend(['-H', self._serverHost])
        if self._serverPort is not None:
            args.extend(['-P', str(self._serverPort)])
        if self._deviceSerial:
            args.extend(['-s', self._deviceSerial])
        args.extend(["shell", cmdline])

        def _timeout():
            self._logger.error("Timeout exceeded for shell call '%s'" % ' '.join(args))

        self._logger.debug("shell - command: %s" % ' '.join(args))
        proc = ProcessHandler(args, processOutputLine=self._log, onTimeout=_timeout)

        if not timeout:
            # We are asserting that all commands will complete in this time unless otherwise specified
            timeout = self.default_timeout

        timeout = int(timeout)
        proc.run(timeout)
        proc.wait()
        output = proc.output

        if output:
            lastline = output[-1]
            if lastline:
                m = re.search('([0-9]+)', lastline)
                if m:
                    return_code = m.group(1)
                    for line in output:
                        outputfile.write(line + '\n')
                    outputfile.seek(-2, 2)
                    outputfile.truncate() # truncate off the return code
                    return int(return_code)

        return None

    def forward(self, local, remote):
        """
        Forward socket connections.

        Forward specs are one of:
          tcp:<port>
          localabstract:<unix domain socket name>
          localreserved:<unix domain socket name>
          localfilesystem:<unix domain socket name>
          dev:<character device name>
          jdwp:<process pid> (remote only)
        """
        if not self._checkCmd(['forward', local, remote], timeout=self.short_timeout) == 0:
            raise DMError("Failed to forward socket connection.")

    def remount(self):
        "Remounts the /system partition on the device read-write."
        return self._checkCmd(['remount'], timeout=self.short_timeout)

    def devices(self):
        "Return a list of connected devices as (serial, status) tuples."
        proc = self._runCmd(['devices'])
        proc.output.pop(0) # ignore first line of output
        devices = []
        for line in proc.output:
            result = re.match('(.*?)\t(.*)', line)
            if result:
                devices.append((result.group(1), result.group(2)))
        return devices

    def _connectRemoteADB(self):
        self._checkCmd(["connect", self.host + ":" + str(self.port)])

    def _disconnectRemoteADB(self):
        self._checkCmd(["disconnect", self.host + ":" + str(self.port)])

    def pushFile(self, localname, destname, retryLimit=None, createDir=True):
        # you might expect us to put the file *in* the directory in this case,
        # but that would be different behaviour from devicemanagerSUT. Throw
        # an exception so we have the same behaviour between the two
        # implementations
        retryLimit = retryLimit or self.retryLimit
        if self.dirExists(destname):
            raise DMError("Attempted to push a file (%s) to a directory (%s)!" %
                          (localname, destname))
        if not os.access(localname, os.F_OK):
            raise DMError("File not found: %s" % localname)

        proc = self._runCmd(["push", os.path.realpath(localname), destname],
                retryLimit=retryLimit)
        if proc.returncode != 0:
            raise DMError("Error pushing file %s -> %s; output: %s" % (localname, destname, proc.output))

    def mkDir(self, name):
        result = self._runCmd(["shell", "mkdir", name], timeout=self.short_timeout).output
        if len(result) and 'read-only file system' in result[0].lower():
            raise DMError("Error creating directory: read only file system")

    def pushDir(self, localDir, remoteDir, retryLimit=None, timeout=None):
        # adb "push" accepts a directory as an argument, but if the directory
        # contains symbolic links, the links are pushed, rather than the linked
        # files; we either zip/unzip or re-copy the directory into a temporary
        # one to get around this limitation
        retryLimit = retryLimit or self.retryLimit
        if not self.dirExists(remoteDir):
            self.mkDirs(remoteDir+"/x")
        if self._useZip:
            try:
                localZip = tempfile.mktemp() + ".zip"
                remoteZip = remoteDir + "/adbdmtmp.zip"
                proc = ProcessHandler(["zip", "-r", localZip, '.'], cwd=localDir,
                              processOutputLine=self._log)
                proc.run()
                proc.wait()
                self.pushFile(localZip, remoteZip, retryLimit=retryLimit, createDir=False)
                mozfile.remove(localZip)
                data = self._runCmd(["shell", "unzip", "-o", remoteZip,
                                     "-d", remoteDir]).output[0]
                self._checkCmd(["shell", "rm", remoteZip],
                               retryLimit=retryLimit, timeout=self.short_timeout)
                if re.search("unzip: exiting", data) or re.search("Operation not permitted", data):
                    raise Exception("unzip failed, or permissions error")
            except:
                self._logger.warning(traceback.format_exc())
                self._logger.warning("zip/unzip failure: falling back to normal push")
                self._useZip = False
                self.pushDir(localDir, remoteDir, retryLimit=retryLimit, timeout=timeout)
        else:
            tmpDir = tempfile.mkdtemp()
            # copytree's target dir must not already exist, so create a subdir
            tmpDirTarget = os.path.join(tmpDir, "tmp")
            shutil.copytree(localDir, tmpDirTarget)
            self._checkCmd(["push", tmpDirTarget, remoteDir],
                           retryLimit=retryLimit, timeout=timeout)
            mozfile.remove(tmpDir)

    def dirExists(self, remotePath):
        self._detectLsModifier()
        data = self._runCmd(["shell", "ls", self._lsModifier, remotePath + '/'],
                            timeout=self.short_timeout).output

        if len(data) == 1:
            res = data[0]
            if "Not a directory" in res or "No such file or directory" in res:
                return False
        return True

    def fileExists(self, filepath):
        self._detectLsModifier()
        data = self._runCmd(["shell", "ls", self._lsModifier, filepath],
                            timeout=self.short_timeout).output
        if len(data) == 1:
            foundpath = data[0].decode('utf-8').rstrip()
            if foundpath == filepath:
                return True
        return False

    def removeFile(self, filename):
        if self.fileExists(filename):
            self._checkCmd(["shell", "rm", filename], timeout=self.short_timeout)

    def removeDir(self, remoteDir):
        if self.dirExists(remoteDir):
            self._checkCmd(["shell", "rm", "-r", remoteDir], timeout=self.short_timeout)
        else:
            self.removeFile(remoteDir.strip())

    def moveTree(self, source, destination):
        self._checkCmd(["shell", "mv", source, destination], timeout=self.short_timeout)

    def copyTree(self, source, destination):
        self._checkCmd(["shell", "dd", "if=%s" % source, "of=%s" % destination])

    def listFiles(self, rootdir):
        self._detectLsModifier()
        data = self._runCmd(["shell", "ls", self._lsModifier, rootdir],
                            timeout=self.short_timeout).output
        data[:] = [item.rstrip('\r\n') for item in data]
        if (len(data) == 1):
            if (data[0] == rootdir):
                return []
            if (data[0].find("No such file or directory") != -1):
                return []
            if (data[0].find("Not a directory") != -1):
                return []
            if (data[0].find("Permission denied") != -1):
                return []
            if (data[0].find("opendir failed") != -1):
                return []
            if (data[0].find("Device or resource busy") != -1):
                return []
        return data

    def getProcessList(self):
        p = self._runCmd(["shell", "ps"], timeout=self.short_timeout)
        # first line is the headers
        p.output.pop(0)
        ret = []
        for proc in p.output:
            els = proc.split()
            # We need to figure out if this is "user pid name" or
            # "pid user vsz stat command"
            if els[1].isdigit():
                ret.append(list([int(els[1]), els[len(els) - 1], els[0]]))
            else:
                ret.append(list([int(els[0]), els[len(els) - 1], els[1]]))
        return ret

    def fireProcess(self, appname, failIfRunning=False):
        """
        Starts a process

        returns: pid

        DEPRECATED: Use shell() or launchApplication() for new code
        """
        #strip out env vars
        parts = appname.split('"');
        if (len(parts) > 2):
            parts = parts[2:]
        return self.launchProcess(parts, failIfRunning)

    def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
        """
        Launches a process, redirecting output to standard out

        WARNING: Does not work how you expect on Android! The application's
        own output will be flushed elsewhere.

        DEPRECATED: Use shell() or launchApplication() for new code
        """
        if cmd[0] == "am":
            self._checkCmd(["shell"] + cmd)
            return outputFile

        acmd = ["-W"]
        cmd = ' '.join(cmd).strip()
        i = cmd.find(" ")
        # SUT identifies the URL by looking for :\\ -- another strategy to consider
        re_url = re.compile('^[http|file|chrome|about].*')
        last = cmd.rfind(" ")
        uri = ""
        args = ""
        if re_url.match(cmd[last:].strip()):
            args = cmd[i:last].strip()
            uri = cmd[last:].strip()
        else:
            args = cmd[i:].strip()
        acmd.append("-n")
        acmd.append(cmd[0:i] + "/.App")
        if args != "":
            acmd.append("--es")
            acmd.append("args")
            acmd.append(args)
        if env != '' and env != None:
            envCnt = 0
            # env is expected to be a dict of environment variables
            for envkey, envval in env.iteritems():
                acmd.append("--es")
                acmd.append("env" + str(envCnt))
                acmd.append(envkey + "=" + envval);
                envCnt += 1
        if uri != "":
            acmd.append("-d")
            acmd.append(uri)

        acmd = ["shell", ' '.join(map(lambda x: '"' + x + '"', ["am", "start"] + acmd))]
        self._logger.info(acmd)
        self._checkCmd(acmd)
        return outputFile

    def killProcess(self, appname, sig=None):
        procs = self.getProcessList()
        for (pid, name, user) in procs:
            if name == appname:
                args = ["shell", "kill"]
                if sig:
                    args.append("-%d" % sig)
                args.append(str(pid))
                p = self._runCmd(args, timeout=self.short_timeout)
                if p.returncode != 0:
                    raise DMError("Error killing process "
                                  "'%s': %s" % (appname, p.output))

    def _runPull(self, remoteFile, localFile):
        """
        Pulls remoteFile from device to host
        """
        try:
            self._runCmd(["pull",  remoteFile, localFile])
        except (OSError, ValueError):
            raise DMError("Error pulling remote file '%s' to '%s'" % (remoteFile, localFile))

    def pullFile(self, remoteFile, offset=None, length=None):
        # TODO: add debug flags and allow for printing stdout
        with mozfile.NamedTemporaryFile() as tf:
            self._runPull(remoteFile, tf.name)
            # we need to reopen the file to get the written contents
            with open(tf.name) as tf2:
                # ADB pull does not support offset and length, but we can
                # instead read only the requested portion of the local file
                if offset is not None and length is not None:
                    tf2.seek(offset)
                    return tf2.read(length)
                elif offset is not None:
                    tf2.seek(offset)
                    return tf2.read()
                else:
                    return tf2.read()

    def getFile(self, remoteFile, localFile):
        self._runPull(remoteFile, localFile)

    def getDirectory(self, remoteDir, localDir, checkDir=True):
        self._runCmd(["pull", remoteDir, localDir]).wait()

    def validateFile(self, remoteFile, localFile):
        md5Remote = self._getRemoteHash(remoteFile)
        md5Local = self._getLocalHash(localFile)
        if md5Remote is None or md5Local is None:
            return None
        return md5Remote == md5Local

    def _getRemoteHash(self, remoteFile):
        """
        Return the md5 sum of a file on the device
        """
        with tempfile.NamedTemporaryFile() as f:
            self._runPull(remoteFile, f.name)

            return self._getLocalHash(f.name)

    def _setupDeviceRoot(self, deviceRoot):
        # user-specified device root, create it and return it
        if deviceRoot:
            self.mkDir(deviceRoot)
            return deviceRoot

        # we must determine the device root ourselves
        paths = [('/storage/sdcard0', 'tests'),
                 ('/storage/sdcard1', 'tests'),
                 ('/sdcard', 'tests'),
                 ('/mnt/sdcard', 'tests'),
                 ('/data/local', 'tests')]
        for (basePath, subPath) in paths:
            if self.dirExists(basePath):
                root = os.path.join(basePath, subPath)
                try:
                    self.mkDir(root)
                    return root
                except:
                    pass

        raise DMError("Unable to set up device root using paths: [%s]"
                        % ", ".join(["'%s'" % os.path.join(b, s) for b, s in paths]))

    def getTempDir(self):
        # Cache result to speed up operations depending
        # on the temporary directory.
        if not self._tempDir:
            self._tempDir = "%s/tmp" % self.deviceRoot
            self.mkDir(self._tempDir)

        return self._tempDir

    def reboot(self, wait = False, **kwargs):
        self._checkCmd(["reboot"])
        if wait:
            self._checkCmd(["wait-for-device"])
            if self._runAdbAsRoot:
                self._adb_root()
            self._checkCmd(["shell", "ls", "/sbin"], timeout=self.short_timeout)

    def updateApp(self, appBundlePath, **kwargs):
        return self._runCmd(["install", "-r", appBundlePath]).output

    def getCurrentTime(self):
        timestr = str(self._runCmd(["shell", "date", "+%s"], timeout=self.short_timeout).output[0])
        if (not timestr or not timestr.isdigit()):
            raise DMError("Unable to get current time using date (got: '%s')" % timestr)
        return int(timestr)*1000

    def getInfo(self, directive=None):
        directive = directive or "all"
        ret = {}
        if directive == "id" or directive == "all":
            ret["id"] = self._runCmd(["get-serialno"], timeout=self.short_timeout).output[0]
        if directive == "os" or directive == "all":
            ret["os"] = self.shellCheckOutput(["getprop", "ro.build.display.id"], timeout=self.short_timeout)
        if directive == "uptime" or directive == "all":
            uptime = self.shellCheckOutput(["uptime"], timeout=self.short_timeout)
            if not uptime:
                raise DMError("error getting uptime")
            m = re.match("up time: ((\d+) days, )*(\d{2}):(\d{2}):(\d{2})", uptime)
            if m:
                uptime = "%d days %d hours %d minutes %d seconds" % tuple(
                    [int(g or 0) for g in m.groups()[1:]])
            ret["uptime"] = uptime
        if directive == "process" or directive == "all":
            data = self.shellCheckOutput(["ps"], timeout=self.short_timeout)
            ret["process"] = data.split('\n')
        if directive == "systime" or directive == "all":
            ret["systime"] = self.shellCheckOutput(["date"], timeout=self.short_timeout)
        if directive == "memtotal" or directive == "all":
            meminfo = {}
            for line in self.pullFile("/proc/meminfo").splitlines():
                key, value = line.split(":")
                meminfo[key] = value.strip()
            ret["memtotal"] = meminfo["MemTotal"]
        if directive == "disk" or directive == "all":
            data = self.shellCheckOutput(["df", "/data", "/system", "/sdcard"], timeout=self.short_timeout)
            ret["disk"] = data.split('\n')
        self._logger.debug("getInfo: %s" % ret)
        return ret

    def uninstallApp(self, appName, installPath=None):
        status = self._runCmd(["uninstall", appName]).output[0].strip()
        if status != 'Success':
            raise DMError("uninstall failed for %s. Got: %s" % (appName, status))

    def uninstallAppAndReboot(self, appName, installPath=None):
        self.uninstallApp(appName)
        self.reboot()

    def _runCmd(self, args, timeout=None, retryLimit=None):
        """
        Runs a command using adb
        If timeout is specified, the process is killed after <timeout> seconds.

        returns: instance of ProcessHandler
        """
        retryLimit = retryLimit or self.retryLimit
        finalArgs = [self._adbPath]
        if self._serverHost is not None:
            finalArgs.extend(['-H', self._serverHost])
        if self._serverPort is not None:
            finalArgs.extend(['-P', str(self._serverPort)])
        if self._deviceSerial:
            finalArgs.extend(['-s', self._deviceSerial])
        finalArgs.extend(args)
        self._logger.debug("_runCmd - command: %s" % ' '.join(finalArgs))
        if not timeout:
            timeout = self.default_timeout

        def _timeout():
            self._logger.error("Timeout exceeded for _runCmd call '%s'" % ' '.join(finalArgs))

        retries = 0
        while retries < retryLimit:
            proc = ProcessHandler(finalArgs, storeOutput=True,
                    processOutputLine=self._log, onTimeout=_timeout)
            proc.run(timeout=timeout)
            proc.returncode = proc.wait()
            if proc.returncode == None:
                proc.kill()
                retries += 1
            else:
                return proc

    # timeout is specified in seconds, and if no timeout is given,
    # we will run until we hit the default_timeout specified in the __init__
    def _checkCmd(self, args, timeout=None, retryLimit=None):
        """
        Runs a command using adb and waits for the command to finish.
        If timeout is specified, the process is killed after <timeout> seconds.

        returns: returncode from process
        """
        retryLimit = retryLimit or self.retryLimit
        finalArgs = [self._adbPath]
        if self._serverHost is not None:
            finalArgs.extend(['-H', self._serverHost])
        if self._serverPort is not None:
            finalArgs.extend(['-P', str(self._serverPort)])
        if self._deviceSerial:
            finalArgs.extend(['-s', self._deviceSerial])
        finalArgs.extend(args)
        self._logger.debug("_checkCmd - command: %s" % ' '.join(finalArgs))
        if not timeout:
            # We are asserting that all commands will complete in this
            # time unless otherwise specified
            timeout = self.default_timeout

        def _timeout():
            self._logger.error("Timeout exceeded for _checkCmd call '%s'" % ' '.join(finalArgs))

        timeout = int(timeout)
        retries = 0
        while retries < retryLimit:
            proc = ProcessHandler(finalArgs, processOutputLine=self._log, onTimeout=_timeout)
            proc.run(timeout=timeout)
            ret_code = proc.wait()
            if ret_code == None:
                proc.kill()
                retries += 1
            else:
                return ret_code

        raise DMError("Timeout exceeded for _checkCmd call after %d retries." % retries)

    def chmodDir(self, remoteDir, mask="777"):
        if (self.dirExists(remoteDir)):
            files = self.listFiles(remoteDir.strip())
            for f in files:
                remoteEntry = remoteDir.strip() + "/" + f.strip()
                if (self.dirExists(remoteEntry)):
                    self.chmodDir(remoteEntry)
                else:
                    self._checkCmd(["shell", "chmod", mask, remoteEntry], timeout=self.short_timeout)
                    self._logger.info("chmod %s" % remoteEntry)
            self._checkCmd(["shell", "chmod", mask, remoteDir], timeout=self.short_timeout)
            self._logger.debug("chmod %s" % remoteDir)
        else:
            self._checkCmd(["shell", "chmod", mask, remoteDir.strip()], timeout=self.short_timeout)
            self._logger.debug("chmod %s" % remoteDir.strip())

    def _verifyADB(self):
        """
        Check to see if adb itself can be executed.
        """
        if self._adbPath != 'adb':
            if not os.access(self._adbPath, os.X_OK):
                raise DMError("invalid adb path, or adb not executable: %s" % self._adbPath)

        try:
            self._checkCmd(["version"], timeout=self.short_timeout)
        except os.error, err:
            raise DMError("unable to execute ADB (%s): ensure Android SDK is installed and adb is in your $PATH" % err)

    def _verifyDevice(self):
        # If there is a device serial number, see if adb is connected to it
        if self._deviceSerial:
            deviceStatus = None
            for line in self._runCmd(["devices"]).output:
                m = re.match('(.+)?\s+(.+)$', line)
                if m:
                    if self._deviceSerial == m.group(1):
                        deviceStatus = m.group(2)
            if deviceStatus == None:
                raise DMError("device not found: %s" % self._deviceSerial)
            elif deviceStatus != "device":
                raise DMError("bad status for device %s: %s" % (self._deviceSerial, deviceStatus))

        # Check to see if we can connect to device and run a simple command
        if not self._checkCmd(["shell", "echo"], timeout=self.short_timeout) == 0:
            raise DMError("unable to connect to device")

    def _checkForRoot(self):
        self._haveRootShell = False
        self._haveSu = False
        # If requested to attempt to run adbd as root, do so before
        # checking whether adbs is running as root.
        if self._runAdbAsRoot:
            self._adb_root()

        # Check whether we _are_ root by default (some development boards work
        # this way, this is also the result of some relatively rare rooting
        # techniques)
        proc = self._runCmd(["shell", "id"], timeout=self.short_timeout)
        if proc.output and 'uid=0(root)' in proc.output[0]:
            self._haveRootShell = True
            # if this returns true, we don't care about su
            return

        # if root shell is not available, check if 'su' can be used to gain
        # root
        def su_id(su_modifier, timeout):
            proc = self._runCmd(["shell", "su", su_modifier, "id"],
                                timeout=timeout)

            # wait for response for maximum of 15 seconds, in case su
            # prompts for a password or triggers the Android SuperUser
            # prompt
            start_time = time.time()
            retcode = None
            while (time.time() - start_time) <= 15 and retcode is None:
                retcode = proc.poll()
            if retcode is None: # still not terminated, kill
                proc.kill()

            if proc.output and 'uid=0(root)' in proc.output[0]:
                return True
            return False

        if su_id('0', self.short_timeout):
            self._haveSu = True
            self._suModifier = '0'
        elif su_id('-c', self.short_timeout):
            self._haveSu = True
            self._suModifier = '-c'

    def _isUnzipAvailable(self):
        data = self._runCmd(["shell", "unzip"]).output
        for line in data:
            if (re.search('Usage', line)):
                return True
        return False

    def _isLocalZipAvailable(self):
        def _noOutput(line):
            # suppress output from zip ProcessHandler
            pass
        try:
            proc = ProcessHandler(["zip", "-?"], storeOutput=False, processOutputLine=_noOutput)
            proc.run()
            proc.wait()
        except:
            return False
        return True

    def _verifyZip(self):
        # If "zip" can be run locally, and "unzip" can be run remotely, then pushDir
        # can use these to push just one file per directory -- a significant
        # optimization for large directories.
        self._useZip = False
        if (self._isUnzipAvailable() and self._isLocalZipAvailable()):
            self._logger.info("will use zip to push directories")
            self._useZip = True
        else:
            raise DMError("zip not available")

    def _adb_root(self):
        """ Some devices require us to reboot adbd as root.
            This function takes care of it.
        """
        if self.processInfo("adbd")[2] != "root":
            self._checkCmd(["root"])
            self._checkCmd(["wait-for-device"])
            if self.processInfo("adbd")[2] != "root":
                raise DMError("We tried rebooting adbd as root, however, it failed.")

    def _detectLsModifier(self):
        if self._lsModifier is None:
            # Check if busybox -1A is required in order to get one
            # file per line.
            output = self._runCmd(["shell", "ls", "-1A", "/"],
                         timeout=self.short_timeout).output
            output = ' '.join(output)
            if 'error: device not found' in output:
                raise DMError(output)
            if "Unknown option '-1'. Aborting." in output:
                self._lsModifier = "-a"
            elif "No such file or directory" in output:
                self._lsModifier = "-a"
            else:
                self._lsModifier = "-1A"

