Ejemplo n.º 1
0
    def scan_device_port(self):
        port = 0
        apktime_path = self._get_apktime_path()
        self.debug("apktime path: " + apktime_path)
        sync_value = get_sync_value(apktime_path, self._cache_dir)
        self.debug('your local sync value is: {}'.format(sync_value))
        uuid = get_apk_created_ticket(apktime_path)
        self.debug('your local uuid value is: {}'.format(uuid))

        for i in range(0, 10):
            cexec([self._adb, 'forward', 'tcp:{}'.format(41128 + i), 'tcp:{}'.format(41128 + i)], callback=None)
            url = 'http://127.0.0.1:{}/checkSync?sync={}&uuid={}'.format(41128 + i, sync_value, uuid)
            result, err, code = curl(url)
            if code == 0 and result is not None:
                result = int(result)
                self.debug('server result is {}'.format(result))
                if result == 0:
                    self.debug('check sync value failed, maybe you need a clean build.')
                    from exceptions import CheckSyncStateException
                    raise CheckSyncStateException('check sync value failed, maybe you need a clean build.',
                                                  'NO CAUSE')
                elif result == -1:
                    continue
                else:
                    port = 41128 + i
                    break

        for i in range(0, 10):
            if (41128 + i) != port:
                cexec([self._adb, 'forward', '--remove', 'tcp:{}'.format(41128 + i)], callback=None)

        return port
Ejemplo n.º 2
0
    def scan_device_port(self, sync_value, uuid):
        port = 0

        for i in range(0, 10):
            cexec([self._adb, 'forward', 'tcp:{}'.format(PORT_START + i), 'tcp:{}'.format(PORT_START + i)],
                  callback=None)
            url = 'http://127.0.0.1:{}/checkSync?sync={}&uuid={}'.format(PORT_START + i, sync_value, uuid)
            result, err, code = curl(url)
            if code == 0 and result is not None:
                result = int(result)
                self.debug('server result is {}'.format(result))
                if result == 0:
                    self.debug('check sync value failed, maybe you need a clean build.')
                    from exceptions import CheckSyncStateException
                    raise CheckSyncStateException('check sync value failed, maybe you need a clean build.',
                                                  'NO CAUSE')
                elif result == -1:
                    continue
                else:
                    port = PORT_START + i
                    break

        for i in range(0, 10):
            if (PORT_START + i) != port:
                cexec([self._adb, 'forward', '--remove', 'tcp:{}'.format(PORT_START + i)], callback=None)

        return port
Ejemplo n.º 3
0
    def wake_up(self, need_protection=False):
        package = self._config['package']
        if 'debug_package' in self._config:
            package = self._config['debug_package']

        wake_up_args = [self._adb, 'shell', 'am', 'startservice', '-n',
                        '{}/{}'.format(package, 'com.antfortune.freeline.FreelineService')]
        if not need_protection:
            wake_up_args.extend(['-e', 'wakeup', 'marker'])
        self.debug('wake up Service: {}'.format(' '.join(wake_up_args)))
        cexec(wake_up_args, callback=None)
Ejemplo n.º 4
0
    def connect_device(self):
        self.debug('start to connect device...')
        if not self.check_installation():
            return
        sync_value, uuid = self._get_check_values()
        self.scan_to_get_port(sync_value, uuid)

        if self._port == 0:
            self.check_device_connection()
            commands = [self._adb, 'uninstall', self._config['debug_package']]
            cexec(commands, callback=None)
        self.debug('find device port: {}'.format(self._port))
Ejemplo n.º 5
0
    def _install_apk(self):
        if self._adb:
            if not os.path.exists(self._apk_path):
                raise FreelineException('apk not found.', 'apk path: {}, not exists.'.format(self._apk_path))

            install_args = [self._adb, 'install', '-r', self._apk_path]
            self.debug('start to install apk to device: {}'.format(' '.join(install_args)))
            output, err, code = cexec(install_args, callback=None)

            if 'Failure' in output:
                self.debug('install apk failed, start to retry.')
                output, err, code = cexec(install_args, callback=None)
                if 'Failure' in output:
                    raise FreelineException('install apk to device failed.', '{}\n{}'.format(output, err))
Ejemplo n.º 6
0
    def run_apt_only(self):
        if self._is_databinding_enabled and self._should_run_databinding_apt():
            apt_args = self._generate_java_compile_args(extra_javac_args_enabled=True)
            self.debug('apt exec: ' + ' '.join(apt_args))
            output, err, code = cexec(apt_args, callback=None)

            if code != 0:
                raise FreelineException('apt compile failed.', '{}\n{}'.format(output, err))

            if self._apt_output_dir and os.path.exists(self._apt_output_dir):
                apt_cache_path = os.path.join(self._config['build_cache_dir'], 'apt_files_stat_cache.json')
                if os.path.exists(apt_cache_path):
                    apt_cache = load_json_cache(apt_cache_path)
                for dirpath, dirnames, files in os.walk(self._apt_output_dir):
                    for fn in files:
                        fpath = os.path.join(dirpath, fn)
                        if apt_cache and self._name in apt_cache:
                            if fpath in apt_cache[self._name]:
                                new_md5 = get_md5(fpath)
                                if new_md5 != apt_cache[self._name][fpath]['md5']:
                                    self.debug('detect new md5 value, add apt file to change list: {}'.format(fpath))
                                    self._changed_files['src'].append(fpath)
                            else:
                                self.debug('find new apt file, add to change list: {}'.format(fpath))
                                self._changed_files['src'].append(fpath)
                        else:
                            self.debug('apt cache not found, add to change list: {}'.format(fpath))
                            self._changed_files['src'].append(fpath)
Ejemplo n.º 7
0
    def _check_connection(self):
        self.debug('check device\' connection...')
        commands = [self._adb, 'devices']
        output, err, code = cexec(commands, callback=None)
        if code == 0:
            devices = output.strip().split('\n')
            length = len(devices)
            from exceptions import UsbConnectionException
            if length < 2:
                raise UsbConnectionException('No device\'s connection found',
                                             '\tUse `adb devices` to check your device connection')
            if length > 2:
                raise UsbConnectionException('More than 1 device connect',
                                             '\tOnly 1 device allowed, '
                                             'use `adb devices` to check your devices\' connection')
            for content in devices:
                if content.find('offline') <> -1:
                    raise UsbConnectionException('Device is connected but offline',
                                                '\tPlease replug in device')

                if content.find('unauthorized') <> -1:
                    raise UsbConnectionException('Device is connected but unauthorized',
                                                '\tReplug in device and accept authorization as usual')

                if not (content.find('device') > -1):
                    raise UsbConnectionException('Device is connected but unknown status',
                                                '\tPlease replug in device')
Ejemplo n.º 8
0
 def execute(self):
     command = '{} -q checkBeforeCleanBuild'.format(get_gradle_executable(self._config))
     output, err, code = cexec(command.split(' '), callback=None)
     if code != 0:
         from exceptions import FreelineException
         raise FreelineException('freeline failed when read project info with script: {}'.format(command),
                                 '{}\n{}'.format(output, err))
Ejemplo n.º 9
0
    def run_retrolambda(self):
        if self._is_retrolambda_enabled:
            lambda_config = self._config['retrolambda'][self._name]
            target_dir = self._finder.get_patch_classes_cache_dir()
            jar_args = [Builder.get_java(self._config),
                        '-Dretrolambda.inputDir={}'.format(target_dir),
                        '-Dretrolambda.outputDir={}'.format(target_dir)]

            if lambda_config['supportIncludeFiles']:
                include_files = []
                classes = []
                for dirpath, dirnames, files in os.walk(target_dir):
                    for fn in files:
                        if fn.endswith('.class'):
                            classes.append(os.path.relpath(os.path.join(dirpath, fn), target_dir))

                src_dirs = self._config['project_source_sets'][self._name]['main_src_directory']
                for fpath in self._changed_files['src']:
                    short_path = fpath.replace('.java', '.class')
                    for src_dir in src_dirs:
                        if src_dir in short_path:
                            short_path = os.path.relpath(fpath, src_dir).replace('.java', '')
                            break

                    for clazz in classes:
                        if short_path + '.class' in clazz or short_path + '$' in clazz or 'R.class' in clazz \
                                or 'R$' in clazz or short_path + '_' in clazz:
                            include_file = os.path.join(target_dir, clazz)
                            if os.path.exists(include_file):
                                self.debug('incremental build lambda file: {}'.format(include_file))
                                include_files.append(include_file)

                include_files_param = os.pathsep.join(include_files)
                if len(include_files_param) > 3496:
                    include_files_path = os.path.join(self._cache_dir, self._name, 'retrolambda_inc.list')
                    self.__save_parms_to_file(include_files_path, include_files)
                    jar_args.append('-Dretrolambda.includedFile={}'.format(include_files_path))
                else:
                    jar_args.append('-Dretrolambda.includedFiles={}'.format(include_files_param))

            lambda_classpaths = [target_dir, lambda_config['rtJar']]
            lambda_classpaths.extend(self._classpaths)
            param = os.pathsep.join(lambda_classpaths)

            if lambda_config['supportIncludeFiles'] and len(param) > 3496:
                classpath_file = os.path.join(self._cache_dir, self._name, 'retrolambda_classpaths.path')
                self.__save_parms_to_file(classpath_file, lambda_classpaths)
                jar_args.append('-Dretrolambda.classpathFile={}'.format(classpath_file))
            else:
                jar_args.append('-Dretrolambda.classpath={}'.format(param))

            jar_args.append('-cp')
            jar_args.append(lambda_config['targetJar'])
            jar_args.append(lambda_config['mainClass'])

            self.debug('retrolambda exec: ' + ' '.join(jar_args))
            output, err, code = cexec(jar_args, callback=None)

            if code != 0:
                raise FreelineException('retrolambda compile failed.', '{}\n{}'.format(output, err))
Ejemplo n.º 10
0
    def run_javac_task(self):
        javacargs = [self._javac, '-encoding', 'UTF-8', '-g']
        if not self._is_retrolambda_enabled:
            javacargs.extend(['-target', '1.7', '-source', '1.7'])

        javacargs.append('-cp')
        javacargs.append(os.pathsep.join(self._classpaths))

        for fpath in self._changed_files['src']:
            javacargs.append(fpath)

        javacargs.extend(self._extra_javac_args)
        javacargs.append('-d')
        javacargs.append(self._finder.get_patch_classes_cache_dir())

        self.debug('javac exec: ' + ' '.join(javacargs))
        output, err, code = cexec(javacargs, callback=None)

        if code != 0:
            raise FreelineException('incremental javac compile failed.', '{}\n{}'.format(output, err))
        else:
            if self._is_r_file_changed:
                old_r_file = self._finder.get_dst_r_path(config=self._config)
                new_r_file = android_tools.DirectoryFinder.get_r_file_path(self._finder.get_backup_dir())
                shutil.copyfile(new_r_file, old_r_file)
                self.debug('copy {} to {}'.format(new_r_file, old_r_file))
Ejemplo n.º 11
0
    def run_desugar_task(self):
        self.debug('========= desugar task ========')
        javaargs = [Builder.get_java(self._config)]
        arguments = ['-jar', Builder.get_desugar()]
        patch_classes_cache_dir = self._finder.get_patch_classes_cache_dir()

        arguments.append('--input')
        arguments.append(patch_classes_cache_dir)
        arguments.append('--output')
        arguments.append(patch_classes_cache_dir)

        # bootclasspath
        arguments.append('--bootclasspath_entry')
        arguments.append(os.path.join(self._config['compile_sdk_directory'], 'android.jar'))

        # classpath
        for path in self._classpaths:
            arguments.append('--classpath_entry')
            arguments.append(path)

        javaargs.extend(arguments)

        self.debug('java exec: ' + ' '.join(javaargs))
        output, err, code = cexec(javaargs, callback=None)

        if code != 0:
            raise FreelineException('desugar failed.', '{}\n{}'.format(output, err))
Ejemplo n.º 12
0
def init():
    project_dir = os.getcwd()
    symlink('freeline', project_dir, 'freeline.py')

    if is_windows:
        symlink('freeline', project_dir, 'freeline_core')

    from gradle_tools import get_all_modules
    modules = get_all_modules(project_dir)
    for m in modules:
        if is_main_project(m['path']):
            main_module = m
            break

    if not main_module:
        raise FreelineException('main module not found', 'set main module first')

    print('find main module: ' + main_module['name'])
    args = []
    if is_windows:
        args.append('gradlew.bat')
    else:
        args.append('./gradlew')
    args.append(':{}:checkBeforeCleanBuild'.format(main_module['name']))
    print('freeline is reading project info, please wait a moment...')
    output, err, code = cexec(args, cwd=project_dir)
    if code != 0:
        raise FreelineException('freeline failed when read project info with script: {}'.format(args),
                                '{}\n{}'.format(output, err))
    print('freeline init success')
Ejemplo n.º 13
0
 def check_installation(self):
     commands = [self._adb, 'shell', 'pm', 'list', 'packages', self._config['debug_package']]
     self.debug(commands)
     output, err, code = cexec(commands, callback=None)
     result = re.findall(self._config['debug_package'].replace('.', '\.') + '\s', output)
     if len(result) == 1:
         return True
     return False
Ejemplo n.º 14
0
 def check_installation(self):
     commands = [self._adb, 'shell', 'pm', 'list', 'packages', self._config['package']]
     output, err, code = cexec(commands, callback=None)
     result = re.findall(self._config['package'].replace('.', '\.') + '\s+\Z', output)
     if len(result) != 1:
         self.debug('No package named {} been installed to your device'.format(self._config['package']))
         from exceptions import NoInstallationException
         raise NoInstallationException(
             'No package named {} been installed to your device'.format(self._config['package']),
             '\tUse `adb shell pm list packages {}` to check app installation.'.format(self._config['package']))
Ejemplo n.º 15
0
    def execute(self):
        command = './gradlew -q checkBeforeCleanBuild'
        if is_windows_system():
            command = 'gradlew.bat -q checkBeforeCleanBuild'

        output, err, code = cexec(command.split(' '), callback=None)
        if code != 0:
            from exceptions import FreelineException
            raise FreelineException('freeline failed when read project info with script: {}'.format(command),
                                    '{}\n{}'.format(output, err))
Ejemplo n.º 16
0
def get_device_sdk_version_by_adb(adb):
    dev_version = 0
    try:
        output = cexec([adb, 'shell', 'getprop ro.build.version.sdk'], callback=None)
        if output and len(output) > 0:
            if isinstance(output, str):
                dev_version = int(output.strip())
            elif isinstance(output, tuple):
                dev_version = int(output[0])
    except:
        pass
    return dev_version
Ejemplo n.º 17
0
    def scan_device_port(self, sync_value, uuid):
        port = 0

        for i in range(0, 10):
            cexec([self._adb, 'forward', 'tcp:{}'.format(PORT_START + i), 'tcp:{}'.format(PORT_START + i)],
                  callback=None)
            url = 'http://127.0.0.1:{}/getSyncTicket'.format(PORT_START + i)
            self.debug('url===='+url)
            result, err, code = curl(url)
            if code == 0 and result is not None:
                try:
                    result = json.loads(result.replace("'", '"'))
                    self.debug(result)
                    if result["apkBuildFlag"] == uuid:
                        port = PORT_START + i
                        break
                    elif result["apkBuildFlag"] is not None:
                        self.debug('apkBuildFlag: {} does not match uuid: {}'.format(result["apkBuildFlag"], uuid))
                        port = -1
                        break
                        
                except Exception, e:
                    pass
Ejemplo n.º 18
0
 def _check_connection(self):
     self.debug('check device\' connection...')
     commands = [self._adb, 'devices']
     output, err, code = cexec(commands, callback=None)
     if code == 0:
         length = len(output.strip().split('\n'))
         from exceptions import UsbConnectionException
         if length < 2:
             raise UsbConnectionException('No device\'s connection found',
                                          '\tUse `adb devices` to check your device connection')
         if length > 2:
             raise UsbConnectionException('More than 1 device connect',
                                          '\tOnly 1 device allowed, '
                                          'use `adb devices` to check your devices\' connection')
Ejemplo n.º 19
0
 def execute(self):
     if is_src_changed(self._cache_dir):
         pending_merge_dexes = self._get_dexes()
         dex_path = get_incremental_dex_path(self._cache_dir)
         if len(pending_merge_dexes) == 1:
             self.debug('just 1 dex need to sync, copy {} to {}'.format(pending_merge_dexes[0], dex_path))
             shutil.copy(pending_merge_dexes[0], dex_path)
         elif len(pending_merge_dexes) > 1:
             dex_path = get_incremental_dex_path(self._cache_dir)
             dex_merge_args = ['java', '-jar', os.path.join('freeline', 'release-tools', 'DexMerge.jar'), dex_path]
             dex_merge_args.extend(pending_merge_dexes)
             self.debug('merge dex exec: ' + ' '.join(dex_merge_args))
             output, err, code = cexec(dex_merge_args, callback=None)
             if code != 0:
                 raise FreelineException('merge dex failed: {}'.format(' '.join(dex_merge_args)),
                                         output + '\n' + err)
Ejemplo n.º 20
0
    def execute(self):
        # reload config
        from dispatcher import read_freeline_config
        self._config = read_freeline_config()

        cwd = self._config['build_script_work_directory'].strip()
        if not cwd or not os.path.isdir(cwd):
            cwd = None

        output, err, code = cexec(self._config['build_script'].split(' '), callback=None, cwd=cwd)
        self.debug(self._config['build_script'])
        self.debug("Gradle build task is running, please wait a minute...")
        if code != 0:
            from exceptions import FreelineException
            raise FreelineException('build failed with script: {}'.format(self._config['build_script']),
                                    '{}\n{}'.format(output, err))
Ejemplo n.º 21
0
    def run_dex_task(self):
        patch_classes_cache_dir = self._finder.get_patch_classes_cache_dir()
        # dex_path = self._finder.get_dst_dex_path()
        dex_path = self._finder.get_patch_dex_dir()
        add_path = None
        if is_windows_system():
            add_path = str(os.path.abspath(os.path.join(self._javac, os.pardir)))
            dex_args = [self._dx, '--dex', '--multi-dex', '--output=' + dex_path, patch_classes_cache_dir]
        else:
            dex_args = [self._dx, '--dex', '--no-optimize', '--force-jumbo', '--multi-dex', '--output=' + dex_path,
                        patch_classes_cache_dir]

        self.debug('dex exec: ' + ' '.join(dex_args))
        output, err, code = cexec(dex_args, add_path=add_path)

        if code != 0:
            raise FreelineException('incremental dex compile failed.', '{}\n{}'.format(output, err))
        else:
            mark_restart_flag(self._cache_dir)
Ejemplo n.º 22
0
    def execute(self):
        # reload config
        from dispatcher import read_freeline_config
        self._config = read_freeline_config()

        cwd = self._config['build_script_work_directory'].strip()
        if not cwd or not os.path.isdir(cwd):
            cwd = None

        command = self._config['build_script']
        command += ' -P freelineBuild=true'
        if 'auto_dependency' in self._config and not self._config['auto_dependency']:
            command += ' -PdisableAutoDependency=true'
        if Logger.debuggable:
            command += ' --stacktrace'
        self.debug(command)
        self.debug("Gradle build task is running, please wait a minute...")
        output, err, code = cexec(command.split(' '), callback=None, cwd=cwd)
        if code != 0:
            from exceptions import FreelineException
            raise FreelineException('build failed with script: {}'.format(command), '{}\n{}'.format(output, err))
Ejemplo n.º 23
0
    def run_aapt_task(self):
        self._changed_files['res'].append(self._public_xml_path)
        self._changed_files['res'].append(self._ids_xml_path)

        aapt_args, final_changed_list = self._get_aapt_args()
        self.debug('aapt exec: ' + ' '.join(aapt_args))
        st = time.time()
        output, err, code = cexec(aapt_args, callback=None)

        if code == 0:
            self.debug('aapt use time: {}ms'.format((time.time() - st) * 1000))
            self.debug('merged_changed_list:')
            self.debug(final_changed_list)
            self._backup_res_changed_list(final_changed_list)
            self._handle_with_backup_files(True)
            mark_res_sync_status(self._finder.get_sync_file_path())
        else:
            clean_res_build_job_flag(self._finder.get_res_build_job_path())
            self._handle_with_backup_files(False)
            rollback_backup_files(self._origin_res_list, self._new_res_list)
            raise FreelineException('incremental res build failed.', '{}\n{}'.format(output, err))
Ejemplo n.º 24
0
    def run_aapt_task(self):
        self._changed_files['res'].append(self._public_xml_path)
        self._changed_files['res'].append(self._ids_xml_path)

        aapt_args, final_changed_list = self._get_aapt_args()
        self.debug('aapt exec: ' + ' '.join(aapt_args))
        st = time.time()
        output, err, code = cexec(aapt_args, callback=None)

        if code == 0:
            self.debug('aapt use time: {}ms'.format((time.time() - st) * 1000))
            self.debug('merged_changed_list:')
            self.debug(final_changed_list)
            self._backup_res_changed_list(final_changed_list)
            self._handle_with_backup_files(True)
            mark_res_sync_status(self._finder.get_sync_file_path())
        else:
            clean_res_build_job_flag(self._finder.get_res_build_job_path())
            self._handle_with_backup_files(False)
            rollback_backup_files(self._origin_res_list, self._new_res_list)
            raise FreelineException('incremental res build failed.', '{}\n{}'.format(output, err))
Ejemplo n.º 25
0
    def run_javac_task(self):
        javacargs = [self._javac, '-target', '1.7', '-source', '1.7', '-encoding', 'UTF-8', '-g', '-cp',
                     os.pathsep.join(self._classpaths)]
        for fpath in self._changed_files['src']:
            javacargs.append(fpath)

        javacargs.extend(self._extra_javac_args)
        javacargs.append('-d')
        javacargs.append(self._finder.get_patch_classes_cache_dir())

        self.debug('javac exec: ' + ' '.join(javacargs))
        output, err, code = cexec(javacargs, callback=None)

        if code != 0:
            raise FreelineException('incremental javac compile failed.', '{}\n{}'.format(output, err))
        else:
            if self._is_r_file_changed:
                old_r_file = self._finder.get_dst_r_path(config=self._config)
                new_r_file = DirectoryFinder.get_r_file_path(self._finder.get_backup_dir())
                shutil.copyfile(new_r_file, old_r_file)
                self.debug('copy {} to {}'.format(new_r_file, old_r_file))
Ejemplo n.º 26
0
    def run_javac_task(self):
        if self._is_only_r_changed() and not self._is_other_modules_has_src_changed:
            self._is_need_javac = False
            android_tools.clean_src_changed_flag(self._cache_dir)
            self.debug('apt process do not generate new files, ignore javac task.')
            return

        extra_javac_args_enabled = not (self._is_databinding_enabled and self._should_run_databinding_apt())
        javacargs = self._generate_java_compile_args(extra_javac_args_enabled=extra_javac_args_enabled)

        self.debug('javac exec: ' + ' '.join(javacargs))
        output, err, code = cexec(javacargs, callback=None)

        if code != 0:
            raise FreelineException('incremental javac compile failed.', '{}\n{}'.format(output, err))
        else:
            if self._is_r_file_changed:
                old_r_file = self._finder.get_dst_r_path(config=self._config)
                new_r_file = android_tools.DirectoryFinder.get_r_file_path(self._finder.get_backup_dir())
                if old_r_file and new_r_file:
                    shutil.copyfile(new_r_file, old_r_file)
                    self.debug('copy {} to {}'.format(new_r_file, old_r_file))
Ejemplo n.º 27
0
 def execute(self):
     if is_src_changed(self._cache_dir):
         pending_merge_dexes = self._get_dexes()
         dex_path = get_incremental_dex_path(self._cache_dir)
         if len(pending_merge_dexes) == 1:
             self.debug('just 1 dex need to sync, copy {} to {}'.format(
                 pending_merge_dexes[0], dex_path))
             shutil.copy(pending_merge_dexes[0], dex_path)
         elif len(pending_merge_dexes) > 1:
             dex_path = get_incremental_dex_path(self._cache_dir)
             dex_merge_args = [
                 'java', '-jar',
                 os.path.join('freeline', 'release-tools', 'DexMerge.jar'),
                 dex_path
             ]
             dex_merge_args.extend(pending_merge_dexes)
             self.debug('merge dex exec: ' + ' '.join(dex_merge_args))
             output, err, code = cexec(dex_merge_args, callback=None)
             if code != 0:
                 raise FreelineException(
                     'merge dex failed: {}'.format(dex_merge_args),
                     output + '\n' + err)
Ejemplo n.º 28
0
    def run_kotlinc_task(self):
        # todo 检查R的变化
        if self._is_only_r_changed() and not self._is_other_modules_has_src_changed:
            self._is_need_javac = False
            # self._is_need_kotlinc = False
            android_tools.clean_src_changed_flag(self._cache_dir)
            self.debug('apt process do not generate new files, ignore javac task.')
            return
        kotlincargs = self._generate_kotlin_compile_args()
        self.debug('kotlinc exec: ' + ' '.join(kotlincargs))
        output, err, code = cexec(kotlincargs, callback=None)

        if code != 0:
            raise FreelineException('incremental kotlinc compile failed.', '{}\n{}'.format(output, err))
        else:
            # todo 这个应该是和kotlin没有关系 拷贝R类用的
            if self._is_r_file_changed:
                old_r_file = self._finder.get_dst_r_path(config=self._config)
                new_r_file = android_tools.DirectoryFinder.get_r_file_path(self._finder.get_backup_dir())
                if old_r_file and new_r_file:
                    shutil.copyfile(new_r_file, old_r_file)
                    self.debug('copy {} to {}'.format(new_r_file, old_r_file))
Ejemplo n.º 29
0
    def run_javac_task(self):
        if self._is_only_r_changed() and not self._is_other_modules_has_src_changed:
            self._is_need_javac = False
            android_tools.clean_src_changed_flag(self._cache_dir)
            self.debug('apt process do not generate new files, ignore javac task.')
            return

        extra_javac_args_enabled = not (self._is_databinding_enabled and self._should_run_databinding_apt())
        javacargs = self._generate_java_compile_args(extra_javac_args_enabled=extra_javac_args_enabled)

        self.debug('javac exec: ' + ' '.join(javacargs))
        output, err, code = cexec(javacargs, callback=None)

        if code != 0:
            raise FreelineException('incremental javac compile failed.', '{}\n{}'.format(output, err))
        else:
            if self._is_r_file_changed:
                old_r_file = self._finder.get_dst_r_path(config=self._config)
                new_r_file = android_tools.DirectoryFinder.get_r_file_path(self._finder.get_backup_dir())
                if old_r_file and new_r_file:
                    shutil.copyfile(new_r_file, old_r_file)
                    self.debug('copy {} to {}'.format(new_r_file, old_r_file))
Ejemplo n.º 30
0
    def run_apt_only(self):
        if self._is_databinding_enabled and self._should_run_databinding_apt():
            apt_args = self._generate_java_compile_args(
                extra_javac_args_enabled=True)
            self.debug('apt exec: ' + ' '.join(apt_args))
            output, err, code = cexec(apt_args, callback=None)

            if code != 0:
                raise FreelineException('apt compile failed.',
                                        '{}\n{}'.format(output, err))

            if self._apt_output_dir and os.path.exists(self._apt_output_dir):
                apt_cache_path = os.path.join(self._config['build_cache_dir'],
                                              'apt_files_stat_cache.json')
                if os.path.exists(apt_cache_path):
                    apt_cache = load_json_cache(apt_cache_path)
                for dirpath, dirnames, files in os.walk(self._apt_output_dir):
                    for fn in files:
                        fpath = os.path.join(dirpath, fn)
                        if apt_cache and self._name in apt_cache:
                            if fpath in apt_cache[self._name]:
                                new_md5 = get_md5(fpath)
                                if new_md5 != apt_cache[
                                        self._name][fpath]['md5']:
                                    self.debug(
                                        'detect new md5 value, add apt file to change list: {}'
                                        .format(fpath))
                                    self._changed_files['src'].append(fpath)
                            else:
                                self.debug(
                                    'find new apt file, add to change list: {}'
                                    .format(fpath))
                                self._changed_files['src'].append(fpath)
                        else:
                            self.debug(
                                'apt cache not found, add to change list: {}'.
                                format(fpath))
                            self._changed_files['src'].append(fpath)
Ejemplo n.º 31
0
    def run_dex_task(self):
        patch_classes_cache_dir = self._finder.get_patch_classes_cache_dir()
        dex_path = self._finder.get_dst_dex_path()
        add_path = None
        if is_windows_system():
            add_path = os.path.abspath(os.path.join(self._javac, os.pardir))
            dex_args = [
                self._dx, '--dex', '--output=' + dex_path,
                patch_classes_cache_dir
            ]
        else:
            dex_args = [
                self._dx, '--dex', '--no-optimize', '--force-jumbo',
                '--output=' + dex_path, patch_classes_cache_dir
            ]

        self.debug('dex exec: ' + ' '.join(dex_args))
        output, err, code = cexec(dex_args, add_path=add_path)

        if code != 0:
            raise FreelineException('incremental dex compile failed.',
                                    '{}\n{}'.format(output, err))
        else:
            mark_restart_flag(self._cache_dir)
Ejemplo n.º 32
0
    def run_retrolambda(self):
        if self._is_need_javac and self._is_retrolambda_enabled:
            lambda_config = self._config['retrolambda'][self._name]
            target_dir = self._finder.get_patch_classes_cache_dir()
            jar_args = [
                Builder.get_java(self._config),
                '-Dretrolambda.inputDir={}'.format(target_dir),
                '-Dretrolambda.outputDir={}'.format(target_dir)
            ]

            if lambda_config['supportIncludeFiles']:
                include_files = []
                classes = []
                for dirpath, dirnames, files in os.walk(target_dir):
                    for fn in files:
                        if fn.endswith('.class'):
                            classes.append(
                                os.path.relpath(os.path.join(dirpath, fn),
                                                target_dir))

                src_dirs = self._config['project_source_sets'][
                    self._name]['main_src_directory']
                for fpath in self._changed_files['src']:
                    short_path = fpath.replace('.java', '.class')
                    for src_dir in src_dirs:
                        if src_dir in short_path:
                            short_path = os.path.relpath(fpath,
                                                         src_dir).replace(
                                                             '.java', '')
                            break

                    for clazz in classes:
                        if short_path + '.class' in clazz or short_path + '$' in clazz or 'R.class' in clazz \
                                or 'R$' in clazz or short_path + '_' in clazz:
                            include_file = os.path.join(target_dir, clazz)
                            if os.path.exists(include_file):
                                self.debug(
                                    'incremental build lambda file: {}'.format(
                                        include_file))
                                include_files.append(include_file)

                include_files_param = os.pathsep.join(include_files)
                if len(include_files_param) > 3496:
                    include_files_path = os.path.join(self._cache_dir,
                                                      self._name,
                                                      'retrolambda_inc.list')
                    self.__save_parms_to_file(include_files_path,
                                              include_files)
                    jar_args.append('-Dretrolambda.includedFile={}'.format(
                        include_files_path))
                else:
                    jar_args.append('-Dretrolambda.includedFiles={}'.format(
                        include_files_param))

            lambda_classpaths = [target_dir, lambda_config['rtJar']]
            lambda_classpaths.extend(self._classpaths)
            param = os.pathsep.join(lambda_classpaths)

            if lambda_config['supportIncludeFiles'] and len(param) > 3496:
                classpath_file = os.path.join(self._cache_dir, self._name,
                                              'retrolambda_classpaths.path')
                self.__save_parms_to_file(classpath_file, lambda_classpaths)
                jar_args.append(
                    '-Dretrolambda.classpathFile={}'.format(classpath_file))
            else:
                jar_args.append('-Dretrolambda.classpath={}'.format(param))

            jar_args.append('-cp')
            jar_args.append(lambda_config['targetJar'])
            jar_args.append(lambda_config['mainClass'])

            self.debug('retrolambda exec: ' + ' '.join(jar_args))
            output, err, code = cexec(jar_args, callback=None)

            if code != 0:
                raise FreelineException('retrolambda compile failed.',
                                        '{}\n{}'.format(output, err))
Ejemplo n.º 33
0
 def _launch_application(self):
     if self._package and self._launcher:
         adb_args = [self._adb, 'shell', 'am', 'start', '-n', self._package + '/' + self._launcher]
         self.debug('start to launch application {}/{}'.format(self._package, self._launcher))
         self.debug(' '.join(adb_args))
         cexec(adb_args, callback=None)
Ejemplo n.º 34
0
 def _debug_app(self):
     if self._wait_for_debugger:
         adb_args = [Builder.get_adb(self._config), 'shell', 'am', 'set-debug-app', '-w', self._package]
         self.debug('make application wait for debugger: {}'.format(' '.join(adb_args)))
         cexec(adb_args, callback=None)
Ejemplo n.º 35
0
 def _check_screen_status(self):
     commands = [self._adb, 'shell', 'dumpsys', 'input_method']
     check_str = 'mInteractive=true' if self._is_art else 'mScreenOn=true'
     output, err, code = cexec(commands, callback=None)
     return re.search(check_str, output)
Ejemplo n.º 36
0
 def _launch_application(self):
     if self._package and self._launcher:
         adb_args = [self._adb, 'shell', 'am', 'start', '-n', self._package + '/' + self._launcher]
         self.debug('start to launch application {}/{}'.format(self._package, self._launcher))
         self.debug(' '.join(adb_args))
         cexec(adb_args, callback=None)
Ejemplo n.º 37
0
 def close_connection(self):
     if self._port != 0:
         cexec([self._adb, 'forward', '--remove', 'tcp:{}'.format(self._port)], callback=None)
Ejemplo n.º 38
0
 def _check_screen_status(self):
     commands = [self._adb, 'shell', 'dumpsys', 'input_method']
     check_str = 'mInteractive=true' if self._is_art else 'mScreenOn=true'
     output, err, code = cexec(commands, callback=None)
     return re.search(check_str, output)
Ejemplo n.º 39
0
    def run_aapt(self):
        aapt_args = [Builder.get_aapt(), 'package', '-f', '-I',
                     os.path.join(self._config['compile_sdk_directory'], 'android.jar'),
                     '-M', self._finder.get_dst_manifest_path()]

        for rdir in self._config['project_source_sets'][self._main_module_name]['main_res_directory']:
            if os.path.exists(rdir):
                aapt_args.append('-S')
                aapt_args.append(rdir)

        for rdir in self._module_info['local_dep_res_path']:
            if os.path.exists(rdir):
                aapt_args.append('-S')
                aapt_args.append(rdir)

        if 'extra_dep_res_paths' in self._config and self._config['extra_dep_res_paths'] is not None:
            arr = self._config['extra_dep_res_paths']
            for path in arr:
                path = path.strip()
                if os.path.isdir(path):
                    aapt_args.append('-S')
                    aapt_args.append(path)

        for resdir in self._module_info['dep_res_path']:
            if os.path.exists(resdir):
                aapt_args.append('-S')
                aapt_args.append(resdir)

        aapt_args.extend(['-S', self._finder.get_backup_res_dir()])

        freeline_assets_dir = os.path.join(self._config['build_cache_dir'], 'freeline-assets')
        aapt_args.append('-A')
        aapt_args.append(freeline_assets_dir)

        for adir in self._config['project_source_sets'][self._main_module_name]['main_assets_directory']:
            if os.path.exists(adir):
                aapt_args.append('-A')
                aapt_args.append(adir)

        for m in self._module_info['local_module_dep']:
            if m in self._config['project_source_sets']:
                for adir in self._config['project_source_sets'][m]['main_assets_directory']:
                    if os.path.exists(adir):
                        aapt_args.append('-A')
                        aapt_args.append(adir)

        base_resource_path = get_base_resource_path(self._config['build_cache_dir'])
        aapt_args.append('-m')
        aapt_args.append('-J')
        aapt_args.append(self._finder.get_backup_dir())
        aapt_args.append('--auto-add-overlay')
        aapt_args.append('-F')
        aapt_args.append(base_resource_path)
        aapt_args.append('--debug-mode')
        aapt_args.append('--resoucres-md5-cache-path')
        aapt_args.append(os.path.join(self._config['build_cache_dir'], "arsc_cache.dat"))
        aapt_args.append('--ignore-assets')
        aapt_args.append('public_id.xml:public.xml:*.bak:.*')

        self.debug('aapt exec: ' + ' '.join(aapt_args))
        output, err, code = cexec(aapt_args, callback=None)

        if code != 0:
            raise FreelineException('build base resources failed with: {}'.format(' '.join(aapt_args)),
                                    '{}\n{}'.format(output, err))
        self.debug('generate base resource success: {}'.format(base_resource_path))
Ejemplo n.º 40
0
    def run_retrolambda(self):
        if self._is_need_javac and self._is_retrolambda_enabled:
            lambda_config = self._config['retrolambda'][self._name]
            target_dir = self._finder.get_patch_classes_cache_dir()
            jar_args = [Builder.get_java(self._config),
                        '-Dretrolambda.inputDir={}'.format(target_dir),
                        '-Dretrolambda.outputDir={}'.format(target_dir)]

            if lambda_config['supportIncludeFiles']:
                files_stat_path = os.path.join(self._cache_dir, self._name, 'lambda_files_stat.json')

                include_files = []
                if os.path.exists(files_stat_path):
                    files_stat = load_json_cache(files_stat_path)
                else:
                    files_stat = {}

                for dirpath, dirnames, files in os.walk(target_dir):
                    for fn in files:
                        fpath = os.path.join(dirpath, fn)
                        if fpath not in files_stat:
                            include_files.append(fpath)
                            self.debug('incremental build new lambda file: {}'.format(fpath))
                        else:
                            if os.path.getmtime(fpath) > files_stat[fpath]['mtime']:
                                include_files.append(fpath)
                                self.debug('incremental build lambda file: {}'.format(fpath))

                include_files_param = os.pathsep.join(include_files)
                if len(include_files_param) > 3496:
                    include_files_path = os.path.join(self._cache_dir, self._name, 'retrolambda_inc.list')
                    self.__save_parms_to_file(include_files_path, include_files)
                    jar_args.append('-Dretrolambda.includedFile={}'.format(include_files_path))
                else:
                    jar_args.append('-Dretrolambda.includedFiles={}'.format(include_files_param))

            lambda_classpaths = [target_dir, lambda_config['rtJar']]
            lambda_classpaths.extend(self._classpaths)
            param = os.pathsep.join(lambda_classpaths)

            if lambda_config['supportIncludeFiles'] and len(param) > 3496:
                classpath_file = os.path.join(self._cache_dir, self._name, 'retrolambda_classpaths.path')
                self.__save_parms_to_file(classpath_file, lambda_classpaths)
                jar_args.append('-Dretrolambda.classpathFile={}'.format(classpath_file))
            else:
                jar_args.append('-Dretrolambda.classpath={}'.format(param))

            jar_args.append('-cp')
            jar_args.append(lambda_config['targetJar'])
            jar_args.append(lambda_config['mainClass'])

            self.debug('retrolambda exec: ' + ' '.join(jar_args))
            output, err, code = cexec(jar_args, callback=None)

            if code != 0:
                raise FreelineException('retrolambda compile failed.', '{}\n{}'.format(output, err))

            if lambda_config['supportIncludeFiles']:
                for fpath in include_files:
                    if fpath not in files_stat:
                        files_stat[fpath] = {}
                    files_stat[fpath]['mtime'] = os.path.getmtime(fpath)
                write_json_cache(files_stat_path, files_stat)
                self.debug('save lambda files stat to {}'.format(files_stat_path))
Ejemplo n.º 41
0
 def _turn_on_screen(self):
     commands = [self._adb, 'shell', 'input', 'keyevent', '26']
     cexec(commands, callback=None)
Ejemplo n.º 42
0
 def wake_up(self):
     cexec([
         self._adb, 'shell', 'am', 'start', '-n', '{}/{}'.format(
             self._config['package'], self._config['launcher'])
     ],
           callback=None)
Ejemplo n.º 43
0
    def __update_class_related(self):
        # update class related

        changed_java_files = []

        for module, file_dict in self._changed_files['projects'].iteritems():
            if len(file_dict['src']) > 0:
                changed_java_files.extend(file_dict['src'])

        # process changed java files
        if len(changed_java_files) > 0:
            # update stat_cache.json
            cache_path = os.path.join(self._config['build_cache_dir'], 'stat_cache.json')
            changefiles = ';'.join(changed_java_files)
            class_related_args = ['java', '-jar', os.path.join('freeline', 'release-tools', 'classrelated.jar'), cache_path, changefiles]
            self.debug('update class related: ' + ' '.join(class_related_args))
            #show_gradle_log = False
            #if ArgsConfig.args is not None and ('gradlelog' in ArgsConfig.args and ArgsConfig.args.gradlelog):
            show_gradle_log = True
            output, err, code = cexec(class_related_args, callback=None)

            # read from stat_cache.json
            stat_cache = load_json_cache(cache_path)

            # ignore files
            ignore_java_files = ['UCR.java', 'UCContentProvider.java']

            related_files = []

            package_map = {}

            # read all package java files
            for module, file_dict in stat_cache.items():
                for file in file_dict.keys():
                    package_name = self.__get_package(file)

                    if package_name == '':
                        continue

                    if not package_map.has_key(package_name):
                        same_package_files = []
                        package_map[package_name] = same_package_files
                    else:
                        same_package_files = package_map.get(package_name);
                    same_package_files.append(file)

            # read all related java files
            for file in changed_java_files:
                for module, file_dict in stat_cache.items():
                    if file_dict.has_key(file):
                        file_stat = file_dict[file]
                        if file_stat.has_key('related'):
                            related_files.extend(file_stat['related'])

                # read all same package files
                package_name = self.__get_package(file)
                if package_name != '' and package_map.has_key(package_name):
                    same_package_files = package_map[package_name]
                    related_files.extend(same_package_files)

            related_files = list(set(related_files))

            if len(related_files) > 0:
                # update self._changed_files['projects'] module's file_dict['src']
                for module, file_dict in stat_cache.items():
                    for file in related_files:
                        if file_dict.has_key(file):
                            self._changed_files['projects'][module]['src'].append(file)

                self.debug('updated file changed list:')
                self.debug(self._changed_files)
Ejemplo n.º 44
0
 def close_connection(self):
     if self._port != 0:
         cexec([
             self._adb, 'forward', '--remove', 'tcp:{}'.format(self._port)
         ],
               callback=None)
Ejemplo n.º 45
0
 def _debug_app(self):
     if self._wait_for_debugger:
         adb_args = [Builder.get_adb(self._config), 'shell', 'am', 'set-debug-app', '-w', self._package]
         self.debug('make application wait for debugger: {}'.format(' '.join(adb_args)))
         cexec(adb_args, callback=None)
Ejemplo n.º 46
0
 def _turn_on_screen(self):
     commands = [self._adb, 'shell', 'input', 'keyevent', '26']
     cexec(commands, callback=None)
Ejemplo n.º 47
0
def debug_app(config):
    adb_args = [Builder.get_adb(config), 'shell', 'am', 'set-debug-app', '-w', config['debug_package']]
    cexec(adb_args, callback=None)
Ejemplo n.º 48
0
    def run_retrolambda(self):
        if self._is_need_javac and self._is_retrolambda_enabled:
            lambda_config = self._config['retrolambda'][self._name]
            target_dir = self._finder.get_patch_classes_cache_dir()
            jar_args = [Builder.get_java(self._config),
                        '-Dretrolambda.inputDir={}'.format(target_dir),
                        '-Dretrolambda.outputDir={}'.format(target_dir)]

            if lambda_config['supportIncludeFiles']:
                files_stat_path = os.path.join(self._cache_dir, self._name, 'lambda_files_stat.json')

                include_files = []
                if os.path.exists(files_stat_path):
                    files_stat = load_json_cache(files_stat_path)
                else:
                    files_stat = {}

                for dirpath, dirnames, files in os.walk(target_dir):
                    for fn in files:
                        fpath = os.path.join(dirpath, fn)
                        if fpath not in files_stat:
                            include_files.append(fpath)
                            self.debug('incremental build new lambda file: {}'.format(fpath))
                        else:
                            if os.path.getmtime(fpath) > files_stat[fpath]['mtime']:
                                include_files.append(fpath)
                                self.debug('incremental build lambda file: {}'.format(fpath))

                include_files_param = os.pathsep.join(include_files)
                if len(include_files_param) > 3496:
                    include_files_path = os.path.join(self._cache_dir, self._name, 'retrolambda_inc.list')
                    self.__save_parms_to_file(include_files_path, include_files)
                    jar_args.append('-Dretrolambda.includedFile={}'.format(include_files_path))
                else:
                    jar_args.append('-Dretrolambda.includedFiles={}'.format(include_files_param))

            lambda_classpaths = [target_dir, lambda_config['rtJar']]
            lambda_classpaths.extend(self._classpaths)
            param = os.pathsep.join(lambda_classpaths)

            if lambda_config['supportIncludeFiles'] and len(param) > 3496:
                classpath_file = os.path.join(self._cache_dir, self._name, 'retrolambda_classpaths.path')
                self.__save_parms_to_file(classpath_file, lambda_classpaths)
                jar_args.append('-Dretrolambda.classpathFile={}'.format(classpath_file))
            else:
                jar_args.append('-Dretrolambda.classpath={}'.format(param))

            jar_args.append('-cp')
            jar_args.append(lambda_config['targetJar'])
            jar_args.append(lambda_config['mainClass'])

            self.debug('retrolambda exec: ' + ' '.join(jar_args))
            output, err, code = cexec(jar_args, callback=None)

            if code != 0:
                raise FreelineException('retrolambda compile failed.', '{}\n{}'.format(output, err))

            if lambda_config['supportIncludeFiles']:
                for fpath in include_files:
                    if fpath not in files_stat:
                        files_stat[fpath] = {}
                    files_stat[fpath]['mtime'] = os.path.getmtime(fpath)
                write_json_cache(files_stat_path, files_stat)
                self.debug('save lambda files stat to {}'.format(files_stat_path))
Ejemplo n.º 49
0
class SyncClient(object):
    def __init__(self, is_art, config):
        self._is_art = is_art
        self._config = config
        self._adb = Builder.get_adb(self._config)
        self._cache_dir = self._config['build_cache_dir']
        self._port = 0

    def debug(self, message):
        Logger.debug('[sync_client] {}'.format(message))

    def check_device_connection(self):
        commands = [self._adb, 'devices']
        output, err, code = cexec(commands, callback=None)
        if code == 0:
            devices = output.strip().split('\n')
            length = len(devices)
            from exceptions import UsbConnectionException
            if length < 2:
                self.debug('No device\'s connection found')
                raise UsbConnectionException('No device\'s connection found',
                                             '\tUse `adb devices` to check your device connection')
            if length > 2:
                self.debug('More than 1 devices connect:')
                self.debug(devices)
                raise UsbConnectionException('More than 1 devices connect',
                                             '\tOnly 1 device allowed, '
                                             'use `adb devices` to check your devices\' connection')

    def check_installation(self):
        commands = [self._adb, 'shell', 'pm', 'list', 'packages', self._config['debug_package']]
        self.debug(commands)
        output, err, code = cexec(commands, callback=None)
        result = re.findall(self._config['debug_package'].replace('.', '\.') + '\s', output)
        if len(result) == 1:
            return True
        return False

    def ensure_device_status(self):
        if not self._check_screen_status():
            self.debug('try to turn on your device\'s screen...')
            self._turn_on_screen()

    def connect_device(self):
        self.debug('start to connect device...')
        if not self.check_installation():
            return
        sync_value, uuid = self._get_check_values()
        self.scan_to_get_port(sync_value, uuid)

        if self._port == 0:
            self.check_device_connection()
            commands = [self._adb, 'uninstall', self._config['debug_package']]
            cexec(commands, callback=None)
        self.debug('find device port: {}'.format(self._port))

    def scan_to_get_port(self, sync_value, uuid):
        self._port = self.scan_device_port(sync_value, uuid)

        if self._port == 0:
            for i in range(1, 11):
                need_protection = i <= 1
                self.wake_up(need_protection=need_protection)
                self._port = self.scan_device_port(sync_value, uuid)
                if self._port != 0:
                    break
                time.sleep(0.2)
                self.debug('try to connect device {} times...'.format(i))

    def close_connection(self):
        if self._port != 0:
            cexec([self._adb, 'forward', '--remove', 'tcp:{}'.format(self._port)], callback=None)

    def scan_device_port(self, sync_value, uuid):
        port = 0

        for i in range(0, 10):
            cexec([self._adb, 'forward', 'tcp:{}'.format(PORT_START + i), 'tcp:{}'.format(PORT_START + i)],
                  callback=None)
            url = 'http://127.0.0.1:{}/getSyncTicket'.format(PORT_START + i)
            result, err, code = curl(url)
            if code == 0 and result is not None:
                try:
                    result = json.loads(result.replace("'", '"'))
                    self.debug(result)
                    self.debug("uuid={}".format(uuid))
                    if result["apkBuildFlag"] == uuid:
                        port = PORT_START + i
                        break
                except Exception, e:
                    pass

        for i in range(0, 10):
            if (PORT_START + i) != port:
                cexec([self._adb, 'forward', '--remove', 'tcp:{}'.format(PORT_START + i)], callback=None)

        return port