def ape_task(avd_name, serial, package_name, output_dir, running_minutes,
             mt_is_running):
    sleep_cnt = 0
    while mt_is_running.value == 0 and sleep_cnt < 30:
        time.sleep(1)
        sleep_cnt += 1
    # Something wrong on mtserver, wait 30 seconds
    if sleep_cnt == 30:
        kill_mtserver(serial=serial)
        return

    print('ape_task(): Emulator[{}, {}] Running APE with package {}'.format(
        avd_name, serial, package_name))
    args = '-p {} --running-minutes {} --mt --ape sata'.format(
        package_name, running_minutes)
    with open(os.path.join(output_dir, 'ape_stdout_stderr.txt'), 'wt') as f:
        ret = run_adb_cmd(
            'shell CLASSPATH={} {} {} {} {}'.format(
                os.path.join(TMP_LOCATION,
                             'ape.jar'), '/system/bin/app_process',
                TMP_LOCATION, 'com.android.commands.monkey.Monkey', args),
            stdout_callback=lambda t: f.write(t + '\n'),
            stderr_callback=lambda t: f.write(t + '\n'),
            serial=serial,
        )

    fetch_result(output_dir, serial)
def mt_task(package_name, serial, logging_flag, mt_is_running):
    def stdout_callback(line):
        if line.startswith('Server with uid'):
            mt_is_running.value += 1

    print('Start mtserver...')
    run_adb_cmd('shell /data/local/tmp/mtserver server {} {}'  \
            .format(package_name, logging_flag),
                stdout_callback = stdout_callback,
                stderr_callback = stdout_callback,
                serial=serial)
    kill_mtserver(serial)
def run_ape_with_mt(apk_path, avd_name, libart_path, ape_jar_path,
                    mtserver_path, ape_output_folder, mt_output_folder,
                    running_minutes, force_clear):
    package_name = get_package_name(apk_path)
    print('run_ape_with_mt(): given apk_path {} avd_name {}'.format(
        apk_path, avd_name))

    assert os.path.split(libart_path)[1] == 'libart.so'
    assert os.path.split(mtserver_path)[1] == 'mtserver'
    assert os.path.split(ape_jar_path)[1] == 'ape.jar'

    avd = install_art_ape_mt(avd_name, libart_path, ape_jar_path,
                             mtserver_path, force_clear)

    try:
        install_package(apk_path, serial=avd.serial)
    except RuntimeError as e:
        print(e)
        return True

    kill_mtserver(serial=avd.serial)
    mt_is_running = Value('i', 0)
    mtserver_thread = threading.Thread(target=mt_task,
                                       args=(package_name, mt_output_folder,
                                             avd.serial, "20010107",
                                             mt_is_running))
    apetask_thread = threading.Thread(target=ape_task,
                                      args=(avd_name, avd.serial, package_name,
                                            ape_output_folder, running_minutes,
                                            mt_is_running))

    set_multiprocessing_mode()
    generate_catcher_thread(os.path.join(mt_output_folder, "logcat.txt"),
                            serial=avd.serial)
    mtserver_thread.start()
    apetask_thread.start()
    apetask_thread.join()

    kill_mtserver(serial=avd.serial)
    mtserver_thread.join()
    kill_generated_logcat_processes()
    unset_multiprocessing_mode()

    if mt_is_running.value == 0:  # It failed to run ape/mt
        print('run_ape_with_mt(): failed to run')
        return False
    return True
def ape_task(avd_name, serial, package_name, output_dir, running_minutes, mt_is_running, mtdtarget, no_guide):
    sleep_cnt = 0
    while mt_is_running.value == 0 and sleep_cnt < 30:
        time.sleep(1)
        sleep_cnt += 1
    # Something wrong on mtserver, wait 30 seconds
    if sleep_cnt == 30:
        kill_mtserver(serial=serial)
        return
    assert mtdtarget

    mt_data_dir = os.path.join(output_dir, 'mt_data')
    if not os.path.isdir(mt_data_dir):
        os.makedirs(mt_data_dir)

    if not os.path.isdir(output_dir):
        os.makedirs(output_dir)
    def ape_stdout_callback(line):
        f.write(line + '\n')
        if line.startswith("[APE_MT] mt data "):
            directory = line[len("[APE_MT] mt data "):]
            run_adb_cmd("pull {} {}".format(directory, mt_data_dir), serial=serial)
            print("callback: {} pulled into {}".format(directory, mt_data_dir))
            run_adb_cmd("shell rm -rf {}".format(directory), serial=serial)

    run_adb_cmd("push {} {}".format(mtdtarget_fname, mtdtarget_destname), serial=serial)
    print('ape_task(): Emulator[{}, {}] Running APE with package {}'.format(avd_name, serial, package_name))
    args = '-p {} --running-minutes {} --mt --mtdtarget {} {}--ape sata'.format(package_name, running_minutes, mtdtarget_destname,
        "--no-mtdguide " if no_guide else "")
    with open(os.path.join(output_dir, 'ape_stdout_stderr.txt'), 'wt') as f:
        ret = run_adb_cmd('shell CLASSPATH={} {} {} {} {}'.format(
                os.path.join(TMP_LOCATION, 'ape.jar'),
                '/system/bin/app_process',
                TMP_LOCATION,
                'com.android.commands.monkey.Monkey',
                args),
            stdout_callback = ape_stdout_callback,
            stderr_callback = lambda t:f.write(t + '\n'),
            serial = serial,
        )
    # pull ape results
    try:
        run_adb_cmd('shell rmdir /data/ape/mt_data', serial=serial)
    except RunCmdError as e:
        print(e.message, file=sys.stderr)
    ret = run_adb_cmd('pull /data/ape {}'.format(output_dir), serial=serial)
def mt_task(package_name, output_folder, serial, logging_flag, mt_is_running):
    connections = ConnectionsWithValue(package_name, serial, output_folder,
                                       mt_is_running)

    try:
        print('Start mtserver...')
        out = run_adb_cmd('shell /data/local/tmp/mtserver server {} {}'  \
                .format(package_name, logging_flag),
            stdout_callback = connections.stdout_callback,
            stderr_callback = connections.stderr_callback,
            serial=serial)
    except WrongConnectionState:
        print('CONNECTION: WrongConnectionState. Check follow log...')
        for line in connections.log:
            print(line)

        kill_mtserver(serial)
    except KeyboardInterrupt:
        connections.clean_up("KeyboardInterrupt")
        raise
    except Exception as e:
        connections.clean_up("Exception " + repr(e))
        raise
    connections.clean_up("Normal")
def run_ape_with_mt(apk_path,
                    avd_name,
                    libart_path,
                    ape_path,
                    mtserver_path,
                    output_dir,
                    running_minutes,
                    force_clear,
                    methods,
                    target_all_thread,
                    methodGuide=True):
    package_name = get_package_name(apk_path)
    print('run_ape_with_mt(): given apk_path {} avd_name {}'.format(
        apk_path, avd_name))

    assert os.path.split(libart_path)[1] == 'libart.so'
    assert os.path.split(mtserver_path)[1] == 'mtserver'
    assert os.path.split(ape_path)[1] == 'ape.jar'

    avd = install_art_ape_mt(avd_name, libart_path, ape_path, mtserver_path,
                             force_clear)

    try:
        install_package(apk_path, serial=avd.serial)
    except RuntimeError as e:
        print(e)
        return "install"

    mtdtarget_fname = 'mtdtarget.txt'
    mtdtarget_emulpath = '/data/local/tmp/mtdtarget.txt'
    with open(mtdtarget_fname, 'wt') as f:
        for clsname, mtdname, signature in methods:
            f.write("%s\t%s\t%s\t1\n" %
                    (clsname, mtdname, signature))  # 1: method enter
    run_adb_cmd("push {} {}".format(mtdtarget_fname, mtdtarget_emulpath),
                serial=avd.serial)

    kill_mtserver(serial=avd.serial)
    mt_is_running = Value('i', 0)
    mtserver_thread = threading.Thread(target=mt_task,
                                       args=(package_name, avd.serial,
                                             "00010180", mt_is_running))
    apetask_thread = threading.Thread(target=ape_task,
                                      args=(avd_name, avd.serial, package_name,
                                            output_dir, running_minutes,
                                            mt_is_running, mtdtarget_emulpath,
                                            target_all_thread, methodGuide))

    set_multiprocessing_mode()
    generate_catcher_thread(os.path.join(output_dir, "logcat.txt"),
                            serial=avd.serial)
    mtserver_thread.start()
    apetask_thread.start()
    apetask_thread.join()

    kill_mtserver(serial=avd.serial)
    mtserver_thread.join()
    kill_generated_logcat_processes()
    unset_multiprocessing_mode()

    if mt_is_running.value == 0:  # It failed to run ape/mt
        print('run_ape_with_mt(): failed to run')
        return "rerun"

    # feedback
    # 1. method is not found, then stop experiment this (apk, targeting methods)
    # 2. method is not called
    methods_registered_over_exp = []  # list of registered methods for each run
    logs = []
    try:
        with open(os.path.join(output_dir, "logcat.txt"), 'rt') as f:
            cur_methods_registered = None
            lazy_methods = []
            for line in f:
                '''
                MiniTrace: TargetMethod %s:%s[%s] lazy
                MiniTrace: TargetMethod %s:%s[%s] registered
                MiniTrace: TargetMethod %s:%s[%s] registered lazily
                '''
                if 'MiniTrace' not in line:
                    continue

                line = line.rstrip()
                line = line[line.index('MiniTrace'):]
                if line.startswith("MiniTrace: connection success, received"):
                    lazy_methods = []
                    if cur_methods_registered is not None:
                        methods_registered_over_exp.append(
                            cur_methods_registered)
                    cur_methods_registered = []
                    logs.append(line)
                    continue
                gp = re.match(
                    r'MiniTrace: TargetMethod (.*):(.*)\[(.*)\] ([a-z ]+)',
                    line)
                if gp:
                    logs.append(line)
                    clsname, mtdname, signature, status = gp.groups()
                    if status == 'lazy':
                        assert (clsname, mtdname,
                                signature) in methods, (clsname, mtdname,
                                                        signature, methods)
                        lazy_methods.append((clsname, mtdname, signature))
                    elif status == 'registered':
                        assert (clsname, mtdname,
                                signature) in methods, (clsname, mtdname,
                                                        signature, methods)
                        cur_methods_registered.append(
                            methods.index((clsname, mtdname, signature)))
                    else:
                        assert status == 'registered lazily', status
                        assert clsname[0] == 'L' and clsname[-1] == ';', clsname
                        clsname = clsname[1:-1]
                        assert (clsname, mtdname,
                                signature) in lazy_methods, (clsname, mtdname,
                                                             signature,
                                                             lazy_methods)
                        cur_methods_registered.append(
                            methods.index((clsname, mtdname, signature)))
            if cur_methods_registered is not None:
                methods_registered_over_exp.append(cur_methods_registered)
    except AssertionError as e:
        print("run_ape_with_mt(): Feedback - failed to register methods")
        print(methods_registered_over_exp)
        print('\n'.join(logs))
        print(e)
        traceback.print_exc()
        return "unregistered"
    if all(executed == [] for executed in methods_registered_over_exp):
        print("run_ape_with_mt(): Feedback - failed to register any methods")
        return "unregistered"
    print('run_ape_with_mt(): methods registered...')
    print(methods_registered_over_exp)

    if not methodGuide:
        return "success"

    # 2. method is not called
    with open(os.path.join(output_dir, 'ape_stdout_stderr.txt'), 'rt') as logf:
        for line in logf:
            line = line.rstrip()
            if "met target" in line:
                return "success"

    return "notsearched"