hackedteam/test-av2

View on GitHub
scripts/mobile/hardware/adb.py

Summary

Maintainability
F
3 days
Test Coverage
#!/usr/bin/python

import sys
import subprocess
import json
import re
import shutil
import threading
import os
import zipfile
import time


#adb_path = "/Users/olli/Documents/work/android/android-sdk-macosx/platform-tools/adb"
devices = []  # we found with usb devices actually connected
adb_path = "adb"

temp_remote_path = "/data/local/tmp/in/"

busybox_filename = 'busybox-android'


def call(cmd, device = None):
    if device:
        #print "##DEBUG## calling %s for device %s" % (cmd,device)
        proc = subprocess.call([adb_path,
                                "-s", device] + cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    else:
        #print "##DEBUG## calling %s" % cmd
        proc = subprocess.call([adb_path] + cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    return proc != 0


def execute_no_command_split(cmd, device):

    print "##DEBUG## calling %s for device %s" % (cmd,device)

    proc = subprocess.Popen([adb_path,
           "-s", device, "shell", cmd], stdout=subprocess.PIPE)
    comm = proc.communicate()
    # proc.wait()
    return str(comm[0])


def skype_call(device = None):
    #cmd = "am start -a android.intent.action.MAIN -d skype:echo123?call"
    cmd = '"am start -a android.intent.action.VIEW -d skype:echo123?call"'
    return execute(cmd, device)

def execute(cmd, device=None):
    #print "##DEBUG## calling %s for device %s" % (cmd, device)
    if device:
        proc = subprocess.Popen([adb_path,
                            "-s", device,
                            "shell"] + cmd.split(),
                            stdout=subprocess.PIPE)

    else:
        proc = subprocess.Popen([adb_path,
                            "shell"] + cmd.split(),
                            stdout=subprocess.PIPE)

    comm = proc.communicate()
    return str(comm[0])

def ps(device=None):
    pp = execute("ps", device).strip()
    return pp

def reboot(device = None):
    call("reboot",device)

def get_deviceid(device=None):
    cmd = "dumpsys iphonesubinfo"

    comm =  execute(cmd, device)
    lines = comm.strip()
    devline = lines.split("\n")[2]
    id = devline.split("=")[1].strip()

    if id == 'null':
        cmd = "settings get secure android_id"
        comm =  execute(cmd, device)
        id = comm.strip()

    return id.replace('*','')

def get_properties(device=None):
    def get_prop(property):
        cmd = "getprop %s" % property
        return execute(cmd, device).strip()

    manufacturer = get_prop("ro.product.manufacturer")
    model = get_prop("ro.product.model")
    selinux = get_prop("ro.build.selinux.enforce")
    release_v = get_prop("ro.build.version.release")
#    print manufacturer, model, selinux, release_v
    return { "manufacturer": manufacturer, "model": model, "selinux": selinux, "release":release_v }

#    for line in output.split('\\n'):
#        if 'Device ID' in line:
#            eq = line.find("=")
#            dev_id = line[eq+2:-2]
#            print dev_id
#    return dev_id
    
def install(apk, device=None):
    """ Install melted application on phone
    @param package full path
    @return True/False
    """
    #if os.path.exists(apk) == False:
    #    return False
    if device:
        proc = subprocess.call([adb_path,
                            "-s", device,
                            "install", apk])
                            #,
                            #stdout=subprocess.PIPE)
    else:
        proc = subprocess.call([adb_path,
                                "install", apk])
    if proc != 0:
        return False
    return True

def executeService(apk, device=None):
    """ Execute melted apk on phone
    @param apk class name to run (eg. com.roxy.angrybirds)
    @return True/False
    shell am  startservice -n $CLASS_PACK/
    """
    app = apk + '/.ServiceMain'
    if device:
        proc = subprocess.call([adb_path,
                                "-s", device,
                                "shell", "am", "startservice",
                                "-n", app], stdout=subprocess.PIPE)
    else:
        proc = subprocess.call([adb_path,
                                "shell", "am", "startservice",
                                "-n", app], stdout=subprocess.PIPE)
    if proc != 0:
        return False
    return True

def executeGui(apk, device=None):
    """ Execute melted apk on phone
    @param apk class name to run (eg. com.roxy.angrybirds)
    @return True/False
    shell am  startservice -n $CLASS_PACK/
    """
    app = apk + '/.gui.ASG'
    if device:
        proc = subprocess.call([adb_path,
                                "-s", device,
                                "shell", "am", "start",
                                "-n", app], stdout=subprocess.PIPE)
    else:
        proc = subprocess.call([adb_path,
                                "shell", "am", "start",
                                "-n", app], stdout=subprocess.PIPE)
    if proc != 0:
        return False
    return True


def uninstall(apk, device=None):
    """ Execute melted apk on phone
    @param apk class name to run (eg. com.roxy.angrybirds)
    @return True/False
    """
    #print "##DEBUG## calling uninstall for device %s" % device
    if device:
        proc = subprocess.call([adb_path,
                            "-s", device,
                            "uninstall", apk], stdout=subprocess.PIPE)
    else:
        print "adb uninstall %s" % apk
        proc = subprocess.call([adb_path,
                                "uninstall", apk], stdout=subprocess.PIPE)

    if proc != 0:
        return False

    return True

def get_attached_devices():
    devices = []
    #devices = ""
    # Find All devices connected via USB
    proc = subprocess.Popen([adb_path, "devices"], stdout=subprocess.PIPE)
    output = str(proc.communicate())

    for line in output.split('\\n'):
        if '\\t' in line:
            dev = line.split('\\t')[0]
            props = get_properties(dev)
            #devices += "device: %s model: %s %s\n" % (dev,props["manufacturer"],props["model"])
            devices.append("device: %s model: %s %s" % (dev,props["manufacturer"],props["model"]))

    return devices

#ML
#Copy a single file to an implicit tmp directory
#The destination dir will be /data/local/tmp/in/ (it will be created if nonexistent)
def copy_tmp_file(file_local_path, device=None):

    #print "##DEBUG##  Copying a single file to an implicit tmp directory on device %s" % device

    copy_file(file_local_path, temp_remote_path, False, device)


#ML
#Copy a single file to an explicit directory with unprivileged or ROOT privileges
#The destination dir will be created if nonexistent
#it uses a temp directory ("/data/local/tmp/in/") to pull the file and then with root privileges moves the file.
#if the destination is directory "/data/local/tmp/in/", then it doesn't move the file
def copy_file(file_local_path, remote_path, root=False, device=None):

    #print "##DEBUG##  Copying a single file to a directory on device %s" % device

    print "create dir %s" % remote_path
    #can always create temp dir without root
    executeSU("mkdir" + " " + temp_remote_path, False, device)

    print "adb push %s" % file_local_path
    if device:
        proc = subprocess.call([adb_path,
                    "-s", device,
                    "push", file_local_path, temp_remote_path], stdout=subprocess.PIPE)
    else:
        proc = subprocess.call([adb_path,
                    "push", file_local_path, temp_remote_path], stdout=subprocess.PIPE)

    if remote_path!=temp_remote_path:
            print "create remote destination %s" % remote_path
            print (executeSU("mkdir" + " " + remote_path, root, device))
            #print (executeSU("id", root, device))

            print "move the file to %s" % remote_path

            print (executeSU("dd" + " if=" + temp_remote_path + "/" + os.path.basename(file_local_path) + " of=" + remote_path + "/" + os.path.basename(file_local_path), root, device))


#Retrieves a single file from device temporary folder using adb pull
#local dir should exists!
#works only with temp dir (because does not use ROOT!)
def get_remote_temp_file(remote_filename, local_destination_path, device=None):
    assert os.path.exists(local_destination_path)

    remote_file_fullpath = temp_remote_path + "/" + remote_filename
    print "adb pull from=%s to=%s" % (remote_file_fullpath, local_destination_path)

    if device:
        proc = subprocess.call([adb_path,
            "-s", device,
            "pull", remote_file_fullpath, local_destination_path], stdout=subprocess.PIPE)
    else:
        proc = subprocess.call([adb_path,
            "pull", remote_file_fullpath, local_destination_path], stdout=subprocess.PIPE)


#Retrieves a single file from device from any folder using dd and adb pull
#local dir should exists!
def get_remote_file(remote_source_filename, remote_source_path, local_destination_path, root=True, device=None):
    assert os.path.exists(local_destination_path)

    remote_file_fullpath_src = remote_source_path + "/" + remote_source_filename
    remote_file_fullpath_tmp = temp_remote_path + "/" + remote_source_filename

    print (executeSU("dd" + " if=" + remote_file_fullpath_src + " of=" + remote_file_fullpath_tmp, root, device))

    print (executeSU("chown " + "shell.shell" + " " + remote_file_fullpath_tmp, root, device))

    get_remote_temp_file(remote_source_filename, local_destination_path, device)

    remove_temp_file(remote_source_filename, device)


#ML
#deletes a single file
def remove_file(filename, file_path, root=False, device=None):

    print "##DEBUG##  Deleting a single file from device %s" % device

    toremove = file_path + "/" + filename

    print "removing file %s" % toremove

    executeSU("rm" + " " + toremove, root, device)


def remove_directory(dir_path, root=False, device=None):

    print "##DEBUG##  Deleting %s directory (rm -r) from device %s" % (dir_path, device)

    executeSU("rm -r" + " " + dir_path, root, device)


#ML
#deletes a single file from tmp
def remove_temp_file(filename, device=None):
    remove_file(filename, temp_remote_path, False, device)


def executeSU(cmd, root=False, device=None):

    if root:
        print "##DEBUG## calling %s for device %s with root %s" % (cmd, device, root)
        print "##DEBUG## executing: %s with rilcap" % cmd
        if device:
            proc = subprocess.Popen(
                [adb_path, "shell", "rilcap qzx '" + cmd + "'"], stdout=subprocess.PIPE)
        else:
            proc = subprocess.Popen([adb_path, "shell", "rilcap qzx '" + cmd + "'"], stdout=subprocess.PIPE)

        comm = proc.communicate()
        return str(comm[0])
    else:
        print "##DEBUG## executing: %s withOUT rilcap" % cmd
        return execute(cmd, device)


#This command installs busybox,
def install_busybox(local_path_with_filename, device=None):
    print 'Installing BusyBox'
    copy_tmp_file(local_path_with_filename)
    #renames file to default (busybox-android)
    #since it's just a rename I can use mv
    executeSU("mv" + " " + temp_remote_path + "/" + os.path.basename(local_path_with_filename) + " " + temp_remote_path + "/" + busybox_filename, False, device)


#NB: this command requires install_busybox!
def uninstall_busybox(device=None):
    print 'Removing BusyBox'
    remove_temp_file(busybox_filename, device)


#NB: this command requires install_busybox!
def execute_busybox(cmd, root=False, device=None):
    print 'Executing with BusyBox cmd= %s' % cmd
    executeSU(temp_remote_path + "/" + busybox_filename + " " + cmd, root, device)


def pack_remote(destination_path_and_filename, source_dir, root=False, device=None):
    print 'Packing'
    execute_busybox("tar -zcvf " + destination_path_and_filename + " " + source_dir, root, device)


def unpack_remote(source_path_and_filename, destination_dir, root=False, device=None):
    print 'Unpacking'
    execute_busybox("tar -zxvf " + source_path_and_filename + " -C " + destination_dir, root, device)


def pack_remote_to_local(remote_source_dir, local_path, local_filename, root=False, device=None):
    remote_file_fullpath = temp_remote_path + "/" + local_filename
    pack_remote(remote_file_fullpath, remote_source_dir, root, device)
    get_remote_temp_file(local_filename, local_path, device)
    remove_temp_file(local_filename, device)


def unpack_local_to_remote(local_file_path, local_filename, remote_dir, root=False, device=None):
    remote_file_fullpath = temp_remote_path + "/" + local_filename
    copy_tmp_file(local_file_path + "/" + local_filename, device)
    unpack_remote(remote_file_fullpath, remote_dir, root, device)
    remove_temp_file(local_filename, device)



"""
    def run(self):
        #apk = 'kr.aboy.tools.zip'
        
        # Change configuration
        #print "Updating package %s with new configuration"  % self.apk
        #if not self.sync_conf():
        #    print "problem updating configuration fo %s." % self.apk
        #    sys.exit(1)
        
        # Unzip apk
        output_zip = os.path.join(conf.build_dir, self.apk)
        output_apk = self.unzip(output_zip)
        
        # Test with adb
        # 1. install
        print "Installing %s on %s" % (output_apk, self.device)
        installed = self.install(output_apk)
        if not installed:
            print "%s not installed on %s" % (output_apk,self.device)
            sys.exit(1)
        
        # 2. run on phone
        print "Executing %s on %s" % (output_apk, self.device)
        executed = self.execute(self.apk[:-4])
        if not executed:
            print "%s not executed on %d" % (output_apk,self.device)
            sys.exit(1)
        
        # 3. check (sleep/wait stuff)
        sleep(10)
        
        # 4. assertions
        print "Checking for instances on %s" % self.device

        # 5. Uninstall phase
        print "This is the end, Uninstalling on %s" % self.device
        uninstalled = self.uninstall(self.apk[:-4])
        if not uninstalled:
            print "Uninstall with your Handz..."
            sys.exit(1)

"""

if __name__ == "__main__":
    print get_deviceid()