def get_crashreports(self, serial=None): ''' Print the pending and submitted crash reports on device. The submitted crashs report will be displayed with URL link. @param serial: device serial number. (optional) ''' AdbWrapper.adb_root(serial=serial) logger.info('Getting Crash Reports...') pending, retcode_pending = AdbWrapper.adb_shell( 'ls -al /data/b2g/mozilla/Crash\ Reports/pending', serial=serial) print('Pending Crash Reports:\n{}\n'.format(pending)) submitted, retcode_submitted = AdbWrapper.adb_shell( 'ls -al /data/b2g/mozilla/Crash\ Reports/submitted', serial=serial) print('Submitted Crash Reports:\n{}\n'.format(submitted)) if retcode_submitted == 0: print('The links of Submitted Crash Reports:') for line in submitted.split('\n'): submmited_id = re.sub(r'\.txt\s*$', '', re.sub(r'^.+bp-', '', line)) submitted_url = 'https://crash-stats.mozilla.com/report/index/{}'.format( submmited_id) print(submitted_url)
def get_crashreports(self, serial=None): """ Print the pending and submitted crash reports on device. The submitted crashs report will be displayed with URL link. @param serial: device serial number. (optional) """ AdbWrapper.adb_root(serial=serial) logger.info('Getting Crash Reports...') self.pending_stdout, retcode_pending = AdbWrapper.adb_shell('ls -al "{}"'.format(self.pending_path), serial=serial) print('Pending Crash Reports:\n{}\n'.format(self.pending_stdout)) self.submitted_stdout, retcode_submitted = AdbWrapper.adb_shell('ls -al "{}"'.format(self.submitted_path), serial=serial) print('Submitted Crash Reports:\n{}\n'.format(self.submitted_stdout)) # parse stdout for getting filepath self.pending_files = self._parse_stdout(self.pending_path, self.pending_stdout) self.submitted_files = self._parse_stdout(self.submitted_path, self.submitted_stdout) self.submitted_url_list = [] if retcode_submitted == 0: print('The links of Submitted Crash Reports:') for line in self.submitted_stdout.split('\n'): submmited_id = re.sub(r'\.txt\s*$', '', re.sub(r'^.+bp-', '', line)) submitted_url = 'https://crash-stats.mozilla.com/report/index/{}'.format(submmited_id) self.submitted_url_list.append(submitted_url) print(submitted_url)
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser(description='Enable Certified Apps Debugging.', formatter_class=RawTextHelpFormatter, epilog=textwrap.dedent('''\ Please enable "ADB and Devtools" of device. Ref: - https://developer.mozilla.org/en-US/docs/Tools/WebIDE - https://developer.mozilla.org/en-US/docs/Tools/WebIDE/Running_and_debugging_apps#Debugging_apps ''')) self.arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help=textwrap.dedent('''\ Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable. (default: %(default)s) ''')) self.arg_parser.add_argument('--disable', action='store_true', dest='disable', default=False, help='Disable the privileges. (default: %(default)s)') self.arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help=textwrap.dedent('''\ Turn on verbose output, with all the debug logger. (default: %(default)s) ''')) self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser(description='Check the version information of Firefox OS.', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument('--no-color', action='store_true', dest='no_color', default=False, help='Do not print with color. NO_COLOR will overrides this option.') arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. ' 'Overrides ANDROID_SERIAL environment variable.') arg_parser.add_argument('--log-text', action='store', dest='log_text', default=None, help='Text ouput.') arg_parser.add_argument('--log-json', action='store', dest='log_json', default=None, help='JSON output.') arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign variable self.set_no_color(args.no_color) self.set_serial(args.serial) self.set_log_text(args.log_text) self.set_log_json(args.log_json) # return instance return self
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser( description='Get the Crash Reports from Firefox OS Phone.', formatter_class=ArgumentDefaultsHelpFormatter) self.arg_parser.add_argument( '-s', '--serial', action='store', dest='serial', default=None, help= 'Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable.' ) self.arg_parser.add_argument( '-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser( description='Check the version information of Firefox OS.', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument( '--no-color', action='store_true', dest='no_color', default=False, help='Do not print with color. NO_COLOR will overrides this option.' ) arg_parser.add_argument( '-s', '--serial', action='store', dest='serial', default=None, help= 'Directs command to the device or emulator with the given serial number. ' 'Overrides ANDROID_SERIAL environment variable.') arg_parser.add_argument('--log-text', action='store', dest='log_text', default=None, help='Text ouput.') arg_parser.add_argument('--log-json', action='store', dest='log_json', default=None, help='JSON output.') arg_parser.add_argument( '-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign variable self.set_no_color(args.no_color) self.set_serial(args.serial) self.set_log_text(args.log_text) self.set_log_json(args.log_json) # return instance return self
def backup_sdcard(self, local_dir, serial=None): """ Backup data from device's SDCard to local folder. @param local_dir: the target local folder, will store data from device's SDCard to this folder. """ logger.info('Backing up SD card...') # try to get the /sdcard folder on device output, retcode = AdbWrapper.adb_shell('ls -d {0}; echo $?'.format(self._REMOTE_DIR_SDCARD), serial=serial) output_list = [item for item in re.split(r'\n+', re.sub(r'\r+', '', output)) if item] ret_code = output_list[-1] output_list.remove(output_list[-1]) ret_msg = '\n'.join(output_list) if ret_code == '0': target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) os.makedirs(target_dir) logger.info('Backup: {0} to {1}'.format(self._REMOTE_DIR_SDCARD, target_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_SDCARD, target_dir, serial=serial) except Exception as e: logger.debug(e) logger.error('Can not pull files from {0} to {1}.'.format(self._REMOTE_DIR_SDCARD, target_dir)) logger.info('Backup SD card done.') else: logger.info(ret_msg)
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser(description='Reset Firefox OS Phone.', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number.' 'Overrides ANDROID_SERIAL environment variable.') arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign the variable self.set_serial(args.serial) # return instance return self
def backup_sdcard(self, local_dir, serial=None): """ Backup data from device's SDCard to local folder. @param local_dir: the target local folder, will store data from device's SDCard to this folder. """ logger.info('Backing up SD card...') # try to get the /sdcard folder on device output, retcode = AdbWrapper.adb_shell('ls -d {0}; echo $?'.format( self._REMOTE_DIR_SDCARD), serial=serial) output_list = [ item for item in re.split(r'\n+', re.sub(r'\r+', '', output)) if item ] ret_code = output_list[-1] output_list.remove(output_list[-1]) ret_msg = '\n'.join(output_list) if ret_code == '0': target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) os.makedirs(target_dir) logger.info('Backup: {0} to {1}'.format(self._REMOTE_DIR_SDCARD, target_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_SDCARD, target_dir, serial=serial) except Exception as e: logger.debug(e) logger.error('Can not pull files from {0} to {1}.'.format( self._REMOTE_DIR_SDCARD, target_dir)) logger.info('Backup SD card done.') else: logger.info(ret_msg)
def __init__(self, **kwargs): self._FILE_PROFILE_INI = 'profiles.ini' self._FILE_COMPATIBILITY_INI = 'compatibility.ini' self._LOCAL_DIR_SDCARD = 'sdcard' self._LOCAL_DIR_WIFI = 'wifi' self._LOCAL_FILE_WIFI = 'wifi/wpa_supplicant.conf' self._LOCAL_DIR_B2G = 'b2g-mozilla' self._LOCAL_DIR_DATA = 'data-local' self._LOCAL_DIR_DATA_APPS = 'webapps' self._REMOTE_DIR_SDCARD = '/sdcard/' self._REMOTE_FILE_WIFI = '/data/misc/wifi/wpa_supplicant.conf' self._REMOTE_FILE_WIFI_OWNER = 'system:wifi' self._REMOTE_DIR_B2G = '/data/b2g/mozilla' self._REMOTE_DIR_DATA = '/data/local' self.arg_parser = argparse.ArgumentParser(description='Workaround for backing up and restoring Firefox OS profiles. (BETA)', formatter_class=ArgumentDefaultsHelpFormatter) self.arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable.') br_group = self.arg_parser.add_mutually_exclusive_group(required=True) br_group.add_argument('-b', '--backup', action='store_true', dest='backup', default=False, help='Backup user profile.') br_group.add_argument('-r', '--restore', action='store_true', dest='restore', default=False, help='Restore user profile.') self.arg_parser.add_argument('--sdcard', action='store_true', dest='sdcard', default=False, help='Also backup/restore SD card.') self.arg_parser.add_argument('--no-reboot', action='store_true', dest='no_reboot', default=False, help='Do not reboot B2G after backup/restore.') self.arg_parser.add_argument('-p', '--profile-dir', action='store', dest='profile_dir', default='mozilla-profile', help='Specify the profile folder.') self.arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def backup_sdcard(self, local_dir, serial=None): logger.info('Backing up SD card...') # try to get the /sdcard folder on device output, retcode = AdbWrapper.adb_shell('ls -d {0}; echo $?'.format( self._REMOTE_DIR_SDCARD), serial=serial) output_list = [ item for item in re.split(r'\n+', re.sub(r'\r+', '', output)) if item ] ret_code = output_list[-1] output_list.remove(output_list[-1]) ret_msg = '\n'.join(output_list) if ret_code == '0': target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) os.makedirs(target_dir) logger.info('Backup: {0} to {1}'.format(self._REMOTE_DIR_SDCARD, target_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_SDCARD, target_dir, serial=serial) except: logger.warning('Can not pull files from {0} to {1}'.format( self._REMOTE_DIR_SDCARD, target_dir)) else: logger.info(ret_msg) logger.info('Backup SD card done.')
def get_crashreports(self, serial=None): """ Print the pending and submitted crash reports on device. The submitted crashs report will be displayed with URL link. @param serial: device serial number. (optional) """ AdbWrapper.adb_root(serial=serial) logger.info('Getting Crash Reports...') self.pending_stdout, retcode_pending = AdbWrapper.adb_shell( 'ls -al "{}"'.format(self.pending_path), serial=serial) print('Pending Crash Reports:\n{}\n'.format(self.pending_stdout)) self.submitted_stdout, retcode_submitted = AdbWrapper.adb_shell( 'ls -al "{}"'.format(self.submitted_path), serial=serial) print('Submitted Crash Reports:\n{}\n'.format(self.submitted_stdout)) # parse stdout for getting filepath self.pending_files = self._parse_stdout(self.pending_path, self.pending_stdout) self.submitted_files = self._parse_stdout(self.submitted_path, self.submitted_stdout) self.submitted_url_list = [] if retcode_submitted == 0: print('The links of Submitted Crash Reports:') for line in self.submitted_stdout.split('\n'): submmited_id = re.sub(r'\.txt\s*$', '', re.sub(r'^.+bp-', '', line)) submitted_url = 'https://crash-stats.mozilla.com/report/index/{}'.format( submmited_id) self.submitted_url_list.append(submitted_url) print(submitted_url)
def prepare_step(self): # checking the adb root if not AdbWrapper.adb_root(serial=self.serial): raise Exception('No root permission for shallow flashing.') # checking the adb remount if not AdbWrapper.adb_remount(serial=self.serial): raise Exception('No permission to remount for shallow flashing.') # Stop B2G B2GHelper.stop_b2g(serial=self.serial)
def _check_profile_version(self, local_dir, serial=None): """ Check the versions of backup and device. The lower backup can restore to device. However the higher backup cannot. @param local_dir: the local backup folder. @param serial: device serial number. (optional) @return: True if backup version is lower than device's. @raise exception: if cannot load profiles or versions. """ if self.skip_version_check: logger.info('Skip version check.') return True logger.info('Checking profile...') # get local version if os.path.isdir(local_dir): local_profile_path = self._get_profile_path( os.path.join(local_dir, self._LOCAL_DIR_B2G, self._FILE_PROFILE_INI)) version_of_backup = self._get_version_from_profile( os.path.join(local_dir, self._LOCAL_DIR_B2G, local_profile_path, self._FILE_COMPATIBILITY_INI)) else: raise Exception('Can not load profile from [{}]'.format(os.path.abspath(local_dir))) tmp_dir = None try: # get remote version tmp_dir = tempfile.mkdtemp(prefix='backup_restore_') logger.debug('TEMP Folder for check profile: {}'.format(tmp_dir)) try: AdbWrapper.adb_pull(os.path.join(self._REMOTE_DIR_B2G, self._FILE_PROFILE_INI), tmp_dir, serial=serial) except: raise Exception( 'Can not pull {2} from {0} to {1}. ' 'Please run with --skip-version-check if you want to restore.'.format( self._REMOTE_DIR_B2G, tmp_dir, self._FILE_PROFILE_INI)) remote_profile_path = self._get_profile_path(os.path.join(tmp_dir, self._FILE_PROFILE_INI)) try: AdbWrapper.adb_pull( os.path.join(self._REMOTE_DIR_B2G, remote_profile_path, self._FILE_COMPATIBILITY_INI), tmp_dir, serial=serial) except: raise Exception( 'Can not pull {2} from {0} to {1}. ' 'Please run with --skip-version-check if you want to restore.'.format( self._REMOTE_DIR_B2G, tmp_dir, self._FILE_COMPATIBILITY_INI)) version_of_device = self._get_version_from_profile( os.path.join(os.path.join(tmp_dir, self._FILE_COMPATIBILITY_INI))) # compare return self._compare_version(version_of_backup, version_of_device) finally: if tmp_dir: logger.debug('Removing [{0}] folder...'.format(tmp_dir)) shutil.rmtree(tmp_dir) logger.debug('TEMP Folder for check profile removed: {}'.format(tmp_dir))
def prepare(self): ''' parse args and setup the logging ''' self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def restore_sdcard(self, local_dir, serial=None): logger.info('Restoring SD card...') target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) if os.path.isdir(target_dir): logger.info('Restore: {0} to {1}'.format(target_dir, self._REMOTE_DIR_SDCARD)) try: AdbWrapper.adb_push(target_dir, self._REMOTE_DIR_SDCARD, serial=serial) except: logger.warning('Can not push files from {0} to {1}'.format(target_dir, self._REMOTE_DIR_SDCARD)) else: logger.info('{0}: No such file or directory'.format(target_dir)) return logger.info('Restore SD card done.')
def prepare(self): """ parse args and setup the logging """ self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = "%(levelname)s: %(message)s" logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser(description='Get the Crash Reports from Firefox OS Phone.', formatter_class=ArgumentDefaultsHelpFormatter) self.arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable.') self.arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def _clean_gaia(self): logger.info('Cleaning Gaia profile: Start') command_list = [ 'rm -r /cache/*', 'rm -r /data/b2g/*', 'rm -r /data/local/storage/persistent/*', 'rm -r /data/local/svoperapps', 'rm -r /data/local/webapps', 'rm -r /data/local/user.js', 'rm -r /data/local/permissions.sqlite*', 'rm -r /data/local/OfflineCache', 'rm -r /data/local/indexedDB', 'rm -r /data/local/debug_info_trigger', 'rm -r /system/b2g/webapps' ] for cmd in command_list: AdbWrapper.adb_shell(cmd, serial=self.serial) logger.info('Cleaning Gaia profile: Done')
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser( description='Workaround for backing up and restoring Firefox OS profiles. (BETA)', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. ' 'Overrides ANDROID_SERIAL environment variable.') br_group = arg_parser.add_mutually_exclusive_group(required=True) br_group.add_argument('-b', '--backup', action='store_true', dest='backup', default=False, help='Backup user profile.') br_group.add_argument('-r', '--restore', action='store_true', dest='restore', default=False, help='Restore user profile.') arg_parser.add_argument('--sdcard', action='store_true', dest='sdcard', default=False, help='Also backup/restore SD card.') arg_parser.add_argument('--no-reboot', action='store_true', dest='no_reboot', default=False, help='Do not reboot B2G after backup/restore.') arg_parser.add_argument('-p', '--profile-dir', action='store', dest='profile_dir', default='mozilla-profile', help='Specify the profile folder.') arg_parser.add_argument('--skip-version-check', action='store_true', dest='skip_version_check', default=False, help='Turn off version check between backup profile and device.') arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign the variable self.set_serial(args.serial) if args.backup: self.set_backup(args.backup) elif args.restore: self.set_restore(args.restore) self.set_sdcard(args.sdcard) self.set_no_reboot(args.no_reboot) self.set_profile_dir(args.profile_dir) self.set_skip_version_check(args.skip_version_check) # return instance return self
def reset_phone(self, serial=None): # checking the adb root for backup/restore if not AdbWrapper.adb_root(serial=serial): raise Exception('No root permission for backup and resotre.') # starting to reset logger.info('Starting to Reset Firefox OS Phone...') AdbWrapper.adb_shell('rm -r /cache/*', serial=serial) AdbWrapper.adb_shell('mkdir /cache/recovery', serial=serial) AdbWrapper.adb_shell('echo "--wipe_data" > /cache/recovery/command', serial=serial) AdbWrapper.adb_shell('reboot recovery', serial=serial) logger.info('Reset Firefox OS Phone done.')
def _push_gecko(self, source_dir): # push into device logger.info('Pushing Gecko: Start') gecko_dir = os.path.join(source_dir, 'b2g') # push target_path = '/system/b2g/' logger.debug('adb push {} to {}'.format(gecko_dir, target_path)) AdbWrapper.adb_push(gecko_dir, target_path, serial=self.serial) # set excutable source_files = os.listdir(gecko_dir) executable_files = [os.path.join('/system/b2g/', f) for f in source_files if os.access(os.path.join(gecko_dir, f), os.X_OK)] logger.debug('Add executed permission on device: {}'.format(executable_files)) for file in executable_files: AdbWrapper.adb_shell('chmod 777 {}'.format(file), serial=self.serial) logger.info('Pushing Gecko: Done')
def get_crashreports(self, serial=None): AdbWrapper.adb_root(serial=serial) logger.info('Getting Crash Reports...') pending, retcode_pending = AdbWrapper.adb_shell('ls -al /data/b2g/mozilla/Crash\ Reports/pending', serial=serial) print('Pending Crash Reports:\n{}\n'.format(pending)) submitted, retcode_submitted = AdbWrapper.adb_shell('ls -al /data/b2g/mozilla/Crash\ Reports/submitted', serial=serial) print('Submitted Crash Reports:\n{}\n'.format(submitted)) if retcode_submitted == 0: print('The links of Submitted Crash Reports:') for line in submitted.split('\n'): submmited_id = re.sub(r'\.txt\s*$', '', re.sub(r'^.+bp-', '', line)) submitted_url = 'https://crash-stats.mozilla.com/report/index/{}'.format(submmited_id) print(submitted_url)
def run(self): """ Entry point. """ self.devices = AdbWrapper.adb_devices() is_no_color = self.no_color if 'NO_COLOR' in os.environ: try: is_no_color = bool(util.strtobool(os.environ['NO_COLOR'].lower())) except Exception as e: logger.debug(e) logger.error('Invalid NO_COLOR value [{0}].'.format(os.environ['NO_COLOR'])) if len(self.devices) == 0: raise Exception('No device.') elif len(self.devices) >= 1: final_serial = AdbHelper.get_serial(self.serial) if final_serial is None: self.device_info_list = [] for device, state in self.devices.items(): print('Serial: {0} (State: {1})'.format(device, state)) if state == 'device': device_info = self.get_device_info(serial=device) self.print_device_info(device_info, no_color=is_no_color) self.device_info_list.append(device_info) else: print('Skipped.\n') self.device_info_list.append({'Serial': device, 'Skip': True}) else: print('Serial: {0} (State: {1})'.format(final_serial, self.devices[final_serial])) device_info = self.get_device_info(serial=final_serial) self.device_info_list = [device_info] self.print_device_info(device_info, no_color=is_no_color) self._output_log()
def run(self): """ Entry point. """ self.prepare() devices = AdbWrapper.adb_devices() is_no_color = self.args.no_color if "NO_COLOR" in os.environ: try: is_no_color = bool(util.strtobool(os.environ["NO_COLOR"].lower())) except: logger.error("Invalid NO_COLOR value [{0}].".format(os.environ["NO_COLOR"])) if len(devices) == 0: raise Exception("No device.") elif len(devices) >= 1: final_serial = AdbHelper.get_serial(self.args.serial) if final_serial is None: device_info_list = [] for device, state in devices.items(): print ("Serial: {0} (State: {1})".format(device, state)) if state == "device": device_info = self.get_device_info(serial=device) self.print_device_info(device_info, no_color=is_no_color) device_info_list.append(device_info) else: print ("Skipped.\n") device_info_list.append({"Serial": device, "Skip": True}) self.output_log(device_info_list) else: print ("Serial: {0} (State: {1})".format(final_serial, devices[final_serial])) device_info = self.get_device_info(serial=final_serial) self.print_device_info(device_info, no_color=is_no_color) self.output_log([device_info])
def run(self): """ Entry point. """ # get the device's serial number devices = AdbWrapper.adb_devices() if len(devices) == 0: raise Exception('No device.') else: self.serial = AdbHelper.get_serial(self.serial) if self.serial is None: if len(devices) == 1: logger.debug('No serial, and only one device') else: logger.debug( 'No serial, but there are more than one device') raise Exception( 'Please specify the device by --serial option.') else: logger.debug('Setup serial to [{0}]'.format(self.serial)) if self.gaia or self.gecko: self.prepare_step() if self.serial: logger.info('Target device [{0}]'.format(self.serial)) if self.gecko: self.shallow_flash_gecko() if self.gaia: self.shallow_flash_gaia() self.final_step()
def run(self): ''' Entry point. ''' self.prepare() devices = AdbWrapper.adb_devices() is_enable = not self.args.disable if len(devices) == 0: raise Exception('No device.') elif len(devices) >= 1: final_serial = AdbHelper.get_serial(self.args.serial) if final_serial is None: if len(devices) == 1: logger.debug('No serial, and only one device') self.set_certapps(enable=is_enable, serial=final_serial) else: logger.debug( 'No serial, but there are more than one device') raise Exception( 'Please specify the device by --serial option.') else: print('Serial: {0} (State: {1})'.format( final_serial, devices[final_serial])) self.set_certapps(enable=is_enable, serial=final_serial)
def _clean_gaia(self): logger.info('Cleaning Gaia profile: Start') command_list = ['rm -r /cache/*', 'rm -r /data/b2g/*', 'rm -r /data/local/storage/persistent/*', 'rm -r /data/local/svoperapps', 'rm -r /data/local/webapps', 'rm -r /data/local/user.js', 'rm -r /data/local/permissions.sqlite*', 'rm -r /data/local/OfflineCache', 'rm -r /data/local/indexedDB', 'rm -r /data/local/debug_info_trigger', 'rm -r /system/b2g/webapps'] for cmd in command_list: AdbWrapper.adb_shell(cmd, serial=self.serial) logger.info('Cleaning Gaia profile: Done')
def run(self): """ Entry point. """ # get the device's serial number devices = AdbWrapper.adb_devices() if len(devices) == 0: raise Exception('No device.') else: self.serial = AdbHelper.get_serial(self.serial) if self.serial is None: if len(devices) == 1: logger.debug('No serial, and only one device') else: logger.debug('No serial, but there are more than one device') raise Exception('Please specify the device by --serial option.') else: logger.debug('Setup serial to [{0}]'.format(self.serial)) if self.gaia or self.gecko: self.prepare_step() if self.serial: logger.info('Target device [{0}]'.format(self.serial)) if self.gecko: self.shallow_flash_gecko() if self.gaia: self.shallow_flash_gaia() self.final_step()
def check_profile_version(self, local_dir, serial=None): logger.info('Checking profile...') # get local version if os.path.isdir(local_dir): local_config = ConfigParser.ConfigParser() local_config.read(os.path.join(local_dir, self._LOCAL_DIR_B2G, self._FILE_PROFILE_INI)) local_profile_path = local_config.get('Profile0', 'Path') local_config.read(os.path.join(local_dir, self._LOCAL_DIR_B2G, local_profile_path, self._FILE_COMPATIBILITY_INI)) logger.debug('Local Profile: {}'.format(local_config._sections)) version_of_backup = local_config.get('Compatibility', 'LastVersion') logger.info('The Version of Backup Profile: {}'.format(version_of_backup)) else: return False try: # get remote version tmp_dir = tempfile.mkdtemp(prefix='backup_restore_') logger.debug('TEMP Folder for check profile: {}'.format(tmp_dir)) try: AdbWrapper.adb_pull(os.path.join(self._REMOTE_DIR_B2G, self._FILE_PROFILE_INI), tmp_dir, serial=serial) except: logger.warning('Can not pull {2} from {0} to {1}'.format(self._REMOTE_DIR_B2G, tmp_dir, self._FILE_PROFILE_INI)) return False remote_config = ConfigParser.ConfigParser() remote_config.read(os.path.join(tmp_dir, self._FILE_PROFILE_INI)) logger.debug('Remote Profile to get path: {}'.format(remote_config._sections)) remote_profile_path = remote_config.get('Profile0', 'Path') try: AdbWrapper.adb_pull(os.path.join(self._REMOTE_DIR_B2G, remote_profile_path, self._FILE_COMPATIBILITY_INI), tmp_dir, serial=serial) except: logger.warning('Can not pull {2} from {0} to {1}'.format(self._REMOTE_DIR_B2G, tmp_dir, self._FILE_COMPATIBILITY_INI)) return False remote_config.read(os.path.join(tmp_dir, self._FILE_COMPATIBILITY_INI)) logger.debug('Remote Profile: {}'.format(remote_config._sections)) version_of_device = remote_config.get('Compatibility', 'LastVersion') logger.info('The Version of Device Profile: {}'.format(version_of_device)) # compare version_of_backup_float = float(version_of_backup.split('.')[0]) version_of_device_float = float(version_of_device.split('.')[0]) logger.debug('Local Ver: {}, Remote Ver: {}'.format(version_of_backup_float, version_of_device_float)) if version_of_device_float >= version_of_backup_float: return True else: return False finally: logger.debug('Removing [{0}] folder...'.format(tmp_dir)) shutil.rmtree(tmp_dir) logger.debug('TEMP Folder for check profile removed: {}'.format(tmp_dir))
def run(self): """ Entry point. """ self.devices = AdbWrapper.adb_devices() logger.debug("Devices: {}".format(self.devices)) if len(self.devices) < 1: raise Exception("Can not find device, please connect your device.") elif len(self.devices) > 1: raise Exception("Find more than one device, please only connect one device.") # get device name device_name = AdbWrapper.adb_shell("getprop ro.product.device")[0] logger.info("Device found: {}".format(device_name)) if device_name not in self.SUPPORT_DEVICES.keys(): raise Exception("The {} device is not supported.".format(device_name)) # select branch branch = self.select_branch() # select build type postfix = self.select_build() # get namespace and image artifact device_info = self.SUPPORT_DEVICES.get(device_name) namespace = self.NAMESPACE_FORMAT(branch=branch, device=device_info.get("name"), postfix=postfix) artifact = self.ARTIFACT_FORMAT(build_path=self.BUILD_PATH, image=device_info.get("image")) logger.info("Device: {}".format(device_name)) logger.info("Namespace: {}".format(namespace)) logger.info("Artifact: {}".format(artifact)) ret = raw_input( '\nDownload "{artifact}" from "{namespace}".\nRight? [Y/n]'.format(artifact=artifact, namespace=namespace) ) if len(ret) > 0 and ret.lower()[0] == "n": logger.info("Stop.") exit(0) # downloading image logger.info("Downloading image...") local_image = self.download(namespace, artifact) logger.debug("Image file: {}".format(local_image)) # checking file logger.info("Checking file...") if not B2GHelper.check_b2g_image(local_image): raise Exception("This is not B2G image file: {}".format(local_image)) # flashing image logger.info("Flashing image...") self.flash_image(local_image)
def restore_sdcard(self, local_dir, serial=None): logger.info('Restoring SD card...') target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) if os.path.isdir(target_dir): logger.info('Restore: {0} to {1}'.format(target_dir, self._REMOTE_DIR_SDCARD)) try: AdbWrapper.adb_push(target_dir, self._REMOTE_DIR_SDCARD, serial=serial) except: logger.warning('Can not push files from {0} to {1}'.format( target_dir, self._REMOTE_DIR_SDCARD)) else: logger.info('{0}: No such file or directory'.format(target_dir)) return logger.info('Restore SD card done.')
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser(description='Check the version information of Firefox OS.', formatter_class=ArgumentDefaultsHelpFormatter) self.arg_parser.add_argument('--no-color', action='store_true', dest='no_color', default=False, help='Do not print with color. NO_COLOR will overrides this option.') self.arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable.') self.arg_parser.add_argument('--log-text', action='store', dest='log_text', default=None, help='Text ouput.') self.arg_parser.add_argument('--log-json', action='store', dest='log_json', default=None, help='JSON output.') self.arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser( description='Check the version information of Firefox OS.', formatter_class=ArgumentDefaultsHelpFormatter) self.arg_parser.add_argument( '--no-color', action='store_true', dest='no_color', default=False, help='Do not print with color. NO_COLOR will overrides this option.' ) self.arg_parser.add_argument( '-s', '--serial', action='store', dest='serial', default=None, help= 'Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable.' ) self.arg_parser.add_argument('--log-text', action='store', dest='log_text', default=None, help='Text ouput.') self.arg_parser.add_argument('--log-json', action='store', dest='log_json', default=None, help='JSON output.') self.arg_parser.add_argument( '-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def restore_sdcard(self, local_dir, serial=None): ''' Restore data from local folder to device's SDCard. @param local_dir: the source local folder, will get data from this folder and than restore to device's SDCard. ''' logger.info('Restoring SD card...') target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) if os.path.isdir(target_dir): logger.info('Restore: {0} to {1}'.format(target_dir, self._REMOTE_DIR_SDCARD)) try: AdbWrapper.adb_push(target_dir, self._REMOTE_DIR_SDCARD, serial=serial) except: logger.error('Can not push files from {0} to {1}'.format(target_dir, self._REMOTE_DIR_SDCARD)) logger.info('Restore SD card done.') else: logger.info('{0}: No such file or directory'.format(target_dir))
def __init__(self, **kwargs): self.arg_parser = argparse.ArgumentParser( description='Enable Certified Apps Debugging.', formatter_class=RawTextHelpFormatter, epilog=textwrap.dedent('''\ Please enable "ADB and Devtools" of device. Ref: - https://developer.mozilla.org/en-US/docs/Tools/WebIDE - https://developer.mozilla.org/en-US/docs/Tools/WebIDE/Running_and_debugging_apps#Debugging_apps ''')) self.arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help=textwrap.dedent('''\ Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable. (default: %(default)s) ''')) self.arg_parser.add_argument( '--disable', action='store_true', dest='disable', default=False, help='Disable the privileges. (default: %(default)s)') self.arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help=textwrap.dedent('''\ Turn on verbose output, with all the debug logger. (default: %(default)s) ''')) self.args = self.arg_parser.parse_args() # setup the logging config if self.args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) AdbWrapper.check_adb()
def set_certapps(self, enable=True, serial=None): AdbWrapper.adb_root(serial=serial) logger.info('{} Full Privilege for WebIDE...'.format('Enabling' if enable else 'Disabling')) need_restart = True try: tmp_dir = tempfile.mkdtemp(prefix='enablecertapps_') # get profile folder name xxx.default under /data/b2g/mozilla/ profile_dir_name, retcode = AdbWrapper.adb_shell('ls /data/b2g/mozilla/ | grep default', serial=serial) device_src_file = os.path.join('/data/b2g/mozilla/', profile_dir_name, 'prefs.js') dest_temp_file = os.path.join(tmp_dir, 'prefs.js.origin') try: logger.info('Pulling prefs.js file...') AdbWrapper.adb_pull(device_src_file, dest_temp_file, serial=serial) except: raise Exception('Error pulling prefs.js file.') dest_file = os.path.join(tmp_dir, 'prefs.js') with open(dest_temp_file, 'r') as fr: with open(dest_file, 'w') as fw: match = False is_forbid = 'false' if enable else 'true' logger.debug('is_forbid: [{}]'.format(is_forbid)) for line in fr: if 'devtools.debugger.forbid-certified-apps' in line: logger.debug('line: [{}] to [{}]'.format(line, is_forbid)) if is_forbid in line: # do not need to restart if the setting isn't changed logger.info('The full privilege is already {}.'.format('enabled' if enable else 'disabled')) need_restart = False break else: logger.info('Changing setting of pref.js file...') fw.write('user_pref("devtools.debugger.forbid-certified-apps", {});\n'.format(is_forbid)) match = True else: fw.write(line) if not match: if not enable: # the forbid is true when there is no setting logger.info('The full privilege is already disabled.') need_restart = False else: if need_restart: # adding setting when there is no setting and need to enable certapps logger.info('Adding setting of pref.js file...') fw.write('user_pref("devtools.debugger.forbid-certified-apps", {});\n'.format(is_forbid)) if need_restart: B2GHelper.stop_b2g(serial=serial) try: logger.info('Pushing prefs.js file...') AdbWrapper.adb_push(dest_file, device_src_file, serial=serial) except: raise Exception('Error pushing prefs.js file.') finally: if need_restart: B2GHelper.start_b2g(serial=serial) shutil.rmtree(tmp_dir)
def backup_sdcard(self, local_dir, serial=None): logger.info('Backing up SD card...') # try to get the /sdcard folder on device output, retcode = AdbWrapper.adb_shell('ls -d {0}; echo $?'.format(self._REMOTE_DIR_SDCARD), serial=serial) output_list = [item for item in re.split(r'\n+', re.sub(r'\r+', '', output)) if item] ret_code = output_list[-1] output_list.remove(output_list[-1]) ret_msg = '\n'.join(output_list) if ret_code == '0': target_dir = os.path.join(local_dir, self._LOCAL_DIR_SDCARD) os.makedirs(target_dir) logger.info('Backup: {0} to {1}'.format(self._REMOTE_DIR_SDCARD, target_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_SDCARD, target_dir, serial=serial) except: logger.warning('Can not pull files from {0} to {1}'.format(self._REMOTE_DIR_SDCARD, target_dir)) else: logger.info(ret_msg) logger.info('Backup SD card done.')
def flash_image(self, image): try: temp_dir = tempfile.mkdtemp() logger.debug("Temporary folder: {}".format(temp_dir)) Decompressor().unzip(image, temp_dir) # set the permissions to rwxrwxr-x (509 in python's os.chmod) os.chmod( temp_dir + "/b2g-distro/flash.sh", stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH, ) os.chmod( temp_dir + "/b2g-distro/load-config.sh", stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH, ) while True: os.system("cd " + temp_dir + "/b2g-distro; ./flash.sh -f") # wait for device, and then check version AdbWrapper.adb_wait_for_device(timeout=120) logger.info("Check versions.") checker = VersionChecker() checker.run() # flash more than one device if not self._flash_again(): break finally: try: shutil.rmtree(temp_dir) # delete directory except OSError: logger.debug("Cannot remove temporary folder: {}".format(temp_dir))
def reset_phone(self, serial=None): ''' Reset the B2G device. @param serial: device serial number. (optional) @raise exception: When no root permission for reset device. ''' # checking the adb root for backup/restore if not AdbWrapper.adb_root(serial=serial): raise Exception('No root permission for reset device.') # starting to reset logger.info('Starting to Reset Firefox OS Phone...') AdbWrapper.adb_shell('rm -r /cache/*', serial=serial) AdbWrapper.adb_shell('mkdir /cache/recovery', serial=serial) AdbWrapper.adb_shell('echo "--wipe_data" > /cache/recovery/command', serial=serial) AdbWrapper.adb_shell('reboot recovery', serial=serial) logger.info('Reset Firefox OS Phone done.')
def reset_phone(serial=None): """ Reset the B2G device. @param serial: device serial number. (optional) @raise exception: When no root permission for reset device. """ # checking the adb root for backup/restore if not AdbWrapper.adb_root(serial=serial): raise Exception('No root permission for reset device.') # starting to reset logger.info('Starting to Reset Firefox OS Phone...') AdbWrapper.adb_shell('rm -r /cache/*', serial=serial) AdbWrapper.adb_shell('mkdir /cache/recovery', serial=serial) AdbWrapper.adb_shell('echo "--wipe_data" > /cache/recovery/command', serial=serial) AdbWrapper.adb_shell('reboot recovery', serial=serial) logger.info('Reset Firefox OS Phone done.')
def _check_profile_version(self, local_dir, serial=None): ''' Check the versions of backup and device. The lower backup can restore to device. However the higher backup cannot. @param local_dir: the local backup folder. @param serial: device serial number. (optional) @return: True if backup version is lower than device's. @raise exception: if cannot load profiles or versions. ''' if self.args.skip_version_check: logger.info('Skip version check.') return True logger.info('Checking profile...') # get local version if os.path.isdir(local_dir): local_profile_path = self._get_profile_path(os.path.join(local_dir, self._LOCAL_DIR_B2G, self._FILE_PROFILE_INI)) version_of_backup = self._get_version_from_profile(os.path.join(local_dir, self._LOCAL_DIR_B2G, local_profile_path, self._FILE_COMPATIBILITY_INI)) else: raise Exception('Can not load profile from [{}]'.format(os.path.abspath(local_dir))) try: # get remote version tmp_dir = tempfile.mkdtemp(prefix='backup_restore_') logger.debug('TEMP Folder for check profile: {}'.format(tmp_dir)) try: AdbWrapper.adb_pull(os.path.join(self._REMOTE_DIR_B2G, self._FILE_PROFILE_INI), tmp_dir, serial=serial) except: raise Exception('Can not pull {2} from {0} to {1}. Please run with --skip-version-check if you want to restore.'.format(self._REMOTE_DIR_B2G, tmp_dir, self._FILE_PROFILE_INI)) remote_profile_path = self._get_profile_path(os.path.join(tmp_dir, self._FILE_PROFILE_INI)) try: AdbWrapper.adb_pull(os.path.join(self._REMOTE_DIR_B2G, remote_profile_path, self._FILE_COMPATIBILITY_INI), tmp_dir, serial=serial) except: raise Exception('Can not pull {2} from {0} to {1}. Please run with --skip-version-check if you want to restore.'.format(self._REMOTE_DIR_B2G, tmp_dir, self._FILE_COMPATIBILITY_INI)) version_of_device = self._get_version_from_profile(os.path.join(os.path.join(tmp_dir, self._FILE_COMPATIBILITY_INI))) # compare return self._compare_version(version_of_backup, version_of_device) finally: logger.debug('Removing [{0}] folder...'.format(tmp_dir)) shutil.rmtree(tmp_dir) logger.debug('TEMP Folder for check profile removed: {}'.format(tmp_dir))
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser( description='Workaround for shallow flash Gaia or Gecko into device.', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help='Directs command to the device or emulator with the given serial number. ' 'Overrides ANDROID_SERIAL environment variable.') arg_parser.add_argument('-g', '--gaia', action='store', dest='gaia', default=None, help='Specify the Gaia package. (zip format)') arg_parser.add_argument('-G', '--gecko', action='store', dest='gecko', default=None, help='Specify the Gecko package. (tar.gz format)') arg_parser.add_argument('--keep-profile', action='store_true', dest='keep_profile', default=False, help='Keep user profile of device. Only work with shallow flash Gaia. (BETA)') arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign the variable self.set_serial(args.serial) if args.gaia: if self._is_gaia_package(args.gaia): self.set_gaia(args.gaia) if args.gecko: if self._is_gecko_package(args.gecko): self.set_gecko(args.gecko) self.set_keep_profile(args.keep_profile) # return instance return self
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser(description='Enable/disable Certified Apps Debugging.', formatter_class=RawTextHelpFormatter, epilog=textwrap.dedent("""\ Please enable "ADB and Devtools" of device. Ref: - https://developer.mozilla.org/en-US/docs/Tools/WebIDE - https://developer.mozilla.org/en-US/docs/Tools/WebIDE/Running_and_debugging_apps#Debugging_apps """)) arg_parser.add_argument('-s', '--serial', action='store', dest='serial', default=None, help=textwrap.dedent("""\ Directs command to the device or emulator with the given serial number. Overrides ANDROID_SERIAL environment variable. (default: %(default)s) """)) arg_parser.add_argument('--disable', action='store_true', dest='disable', default=False, help='Disable the privileges. (default: %(default)s)') arg_parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', default=False, help=textwrap.dedent("""\ Turn on verbose output, with all the debug logger. (default: %(default)s) """)) # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign variable self.set_serial(args.serial) self.set_disable(args.disable) # return instance return self
def _push_gecko(self, source_dir): # push into device logger.info('Pushing Gecko: Start') gecko_dir = os.path.join(source_dir, 'b2g') # push target_path = '/system/b2g/' logger.debug('adb push {} to {}'.format(gecko_dir, target_path)) AdbWrapper.adb_push(gecko_dir, target_path, serial=self.serial) # set excutable source_files = os.listdir(gecko_dir) executable_files = [ os.path.join('/system/b2g/', f) for f in source_files if os.access(os.path.join(gecko_dir, f), os.X_OK) ] logger.debug( 'Add executed permission on device: {}'.format(executable_files)) for file in executable_files: AdbWrapper.adb_shell('chmod 777 {}'.format(file), serial=self.serial) logger.info('Pushing Gecko: Done')
def get_crashreports(self, serial=None): AdbWrapper.adb_root(serial=serial) logger.info('Getting Crash Reports...') pending, retcode_pending = AdbWrapper.adb_shell( 'ls -al /data/b2g/mozilla/Crash\ Reports/pending', serial=serial) print('Pending Crash Reports:\n{}\n'.format(pending)) submitted, retcode_submitted = AdbWrapper.adb_shell( 'ls -al /data/b2g/mozilla/Crash\ Reports/submitted', serial=serial) print('Submitted Crash Reports:\n{}\n'.format(submitted)) if retcode_submitted == 0: print('The links of Submitted Crash Reports:') for line in submitted.split('\n'): submmited_id = re.sub(r'\.txt\s*$', '', re.sub(r'^.+bp-', '', line)) submitted_url = 'https://crash-stats.mozilla.com/report/index/{}'.format( submmited_id) print(submitted_url)
def _clean_gecko(self, source_dir): logger.info('Cleaning Gecko profile: Start') command_list = ['rm -r /system/media'] for cmd in command_list: AdbWrapper.adb_shell(cmd, serial=self.serial) gecko_dir = os.path.join(source_dir, 'b2g') source_files = os.listdir(gecko_dir) logger.debug('The files which will push into device: {}'.format(source_files)) adb_stdout, adb_retcode = AdbWrapper.adb_shell('ls /system/b2g/') device_files = adb_stdout.split() logger.debug('The files which on device /system/b2g/: {}'.format(device_files)) removed_files = sorted(list(set(source_files + device_files))) removed_files.remove('defaults') removed_files.remove('webapps') logger.debug('Remove files list: {}'.format(removed_files)) for file in removed_files: AdbWrapper.adb_shell('rm -r /system/b2g/{}'.format(file), serial=self.serial) logger.info('Cleaning Gecko profile: Done')
def _clean_gecko(self, source_dir): logger.info('Cleaning Gecko profile: Start') command_list = ['rm -r /system/media'] for cmd in command_list: AdbWrapper.adb_shell(cmd, serial=self.serial) gecko_dir = os.path.join(source_dir, 'b2g') source_files = os.listdir(gecko_dir) logger.debug( 'The files which will push into device: {}'.format(source_files)) adb_stdout, adb_retcode = AdbWrapper.adb_shell('ls /system/b2g/') device_files = adb_stdout.split() logger.debug( 'The files which on device /system/b2g/: {}'.format(device_files)) removed_files = sorted(list(set(source_files + device_files))) removed_files.remove('defaults') removed_files.remove('webapps') logger.debug('Remove files list: {}'.format(removed_files)) for file in removed_files: AdbWrapper.adb_shell('rm -r /system/b2g/{}'.format(file), serial=self.serial) logger.info('Cleaning Gecko profile: Done')
def run(self): devices = AdbWrapper.adb_devices() if len(devices) == 0: raise Exception('No device.') elif len(devices) >= 1: final_serial = AdbHelper.get_serial(self.args.serial) if final_serial is None: if len(devices) == 1: logger.debug('No serial, and only one device') self.reset_phone(serial=final_serial) else: logger.debug('No serial, but there are more than one device') raise Exception('Please specify the device by --serial option.') else: print('Serial: {0} (State: {1})'.format(final_serial, devices[final_serial])) self.reset_phone(serial=final_serial)
def run(self): ''' Entry point. ''' self.prepare() devices = AdbWrapper.adb_devices() is_no_color = self.args.no_color if 'NO_COLOR' in os.environ: try: is_no_color = bool( util.strtobool(os.environ['NO_COLOR'].lower())) except: logger.error('Invalid NO_COLOR value [{0}].'.format( os.environ['NO_COLOR'])) if len(devices) == 0: raise Exception('No device.') elif len(devices) >= 1: final_serial = AdbHelper.get_serial(self.args.serial) if final_serial is None: device_info_list = [] for device, state in devices.items(): print('Serial: {0} (State: {1})'.format(device, state)) if state == 'device': device_info = self.get_device_info(serial=device) self.print_device_info(device_info, no_color=is_no_color) device_info_list.append(device_info) else: print('Skipped.\n') device_info_list.append({ 'Serial': device, 'Skip': True }) self.output_log(device_info_list) else: print('Serial: {0} (State: {1})'.format( final_serial, devices[final_serial])) device_info = self.get_device_info(serial=final_serial) self.print_device_info(device_info, no_color=is_no_color) self.output_log([device_info])
def backup_profile(self, local_dir, serial=None): logger.info('Backing up profile...') # Backup Wifi wifi_dir = os.path.join(local_dir, self._LOCAL_DIR_WIFI) wifi_file = os.path.join(local_dir, self._LOCAL_FILE_WIFI) os.makedirs(wifi_dir) logger.info('Backing up Wifi information...') try: AdbWrapper.adb_pull(self._REMOTE_FILE_WIFI, wifi_file, serial=serial) except: logger.warning( 'If you don\'t have root permission, you cannot backup Wifi information.' ) # Backup profile b2g_mozilla_dir = os.path.join(local_dir, self._LOCAL_DIR_B2G) os.makedirs(b2g_mozilla_dir) logger.info('Backing up {0} to {1} ...'.format(self._REMOTE_DIR_B2G, b2g_mozilla_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_B2G, b2g_mozilla_dir, serial=serial) except: logger.warning('Can not pull files from {0} to {1}'.format( self._REMOTE_DIR_B2G, b2g_mozilla_dir)) # Backup data/local datalocal_dir = os.path.join(local_dir, self._LOCAL_DIR_DATA) os.makedirs(datalocal_dir) logger.info('Backing up {0} to {1} ...'.format(self._REMOTE_DIR_DATA, datalocal_dir)) try: AdbWrapper.adb_pull(self._REMOTE_DIR_DATA, datalocal_dir, serial=serial) except: logger.warning('Can not pull files from {0} to {1}'.format( self._REMOTE_DIR_DATA, datalocal_dir)) # Remove "marketplace" app and "gaiamobile.org" apps from webapps webapps_dir = datalocal_dir + self._LOCAL_DIR_DATA_APPS for root, dirs, files in os.walk(webapps_dir): if (os.path.basename(root).startswith('marketplace') or os.path.basename(root).endswith('gaiamobile.org') or os.path.basename(root).endswith('allizom.org')): logger.info('Removing Mozilla webapps: [{0}]'.format(root)) shutil.rmtree(root) logger.info('Backup profile done.')
def final_step(self): if self.gaia and not self.keep_profile: # reset phone when flash gaia and not keep profile logger.info('Reset device after shallow flash the Gaia.') PhoneReseter().reset_phone(serial=self.serial) else: # adb shell reboot logger.info('Reboot device.') AdbWrapper.adb_shell('sync', serial=self.serial) AdbWrapper.adb_shell('reboot', serial=self.serial) # wait for device, and then check version AdbWrapper.adb_wait_for_device(timeout=120) logger.info('Check versions.') checker = VersionChecker() checker.set_serial(self.serial) checker.run()
def _push_gaia(self, source_dir): # push into device logger.info('Pushing Gaia: Start') unziped_gaia_dir = os.path.join(source_dir, 'gaia') # push user.js source_user_pref_path = os.path.join(unziped_gaia_dir, 'profile', 'user.js') user_pref_path = os.path.join(source_dir, 'user.js') # prepare the user.js logger.debug('Prepare user.js file') with open(source_user_pref_path, 'r') as fin: with open(user_pref_path, 'w') as fout: for line in fin: fout.write(line.replace('user_pref', 'pref')) user_pref_target_path = '/system/b2g/defaults/pref/' logger.info('push user.js...') logger.debug('adb push {} to {}'.format(user_pref_path, user_pref_target_path)) AdbWrapper.adb_push(user_pref_path, user_pref_target_path, serial=self.serial) # push webapps webapps_path = os.path.join(unziped_gaia_dir, 'profile', 'webapps') webapps_target_path = '/system/b2g/webapps' logger.info('push webapps...') logger.debug('adb push {} to {}'.format(webapps_path, webapps_target_path)) AdbWrapper.adb_push(webapps_path, webapps_target_path, serial=self.serial) # push settings.json settings_path = os.path.join(unziped_gaia_dir, 'profile', 'settings.json') settings_target_path = '/system/b2g/defaults/' logger.info('push settings.json...') logger.debug('adb push {} to {}'.format(settings_path, settings_target_path)) AdbWrapper.adb_push(settings_path, settings_target_path, serial=self.serial) logger.info('Pushing Gaia: Done')
def run(self): """ Entry point. """ devices = AdbWrapper.adb_devices() if len(devices) == 0: raise Exception('No device.') elif len(devices) >= 1: final_serial = AdbHelper.get_serial(self.serial) if final_serial is None: if len(devices) == 1: logger.debug('No serial, and only one device') self.get_crashreports(serial=final_serial) else: logger.debug( 'No serial, but there are more than one device') raise Exception( 'Please specify the device by --serial option.') else: print('Serial: {0} (State: {1})'.format( final_serial, devices[final_serial])) self.get_crashreports(serial=final_serial) self.output_log()
def cli(self): """ Handle the argument parse, and the return the instance itself. """ # argument parser arg_parser = argparse.ArgumentParser( description= 'Workaround for shallow flash Gaia or Gecko into device.', formatter_class=ArgumentDefaultsHelpFormatter) arg_parser.add_argument( '-s', '--serial', action='store', dest='serial', default=None, help= 'Directs command to the device or emulator with the given serial number. ' 'Overrides ANDROID_SERIAL environment variable.') arg_parser.add_argument('-g', '--gaia', action='store', dest='gaia', default=None, help='Specify the Gaia package. (zip format)') arg_parser.add_argument( '-G', '--gecko', action='store', dest='gecko', default=None, help='Specify the Gecko package. (tar.gz format)') arg_parser.add_argument( '--keep-profile', action='store_true', dest='keep_profile', default=False, help= 'Keep user profile of device. Only work with shallow flash Gaia. (BETA)' ) arg_parser.add_argument( '-v', '--verbose', action='store_true', dest='verbose', default=False, help='Turn on verbose output, with all the debug logger.') # parse args and setup the logging args = arg_parser.parse_args() # setup the logging config if args.verbose is True: verbose_formatter = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging.basicConfig(level=logging.DEBUG, format=verbose_formatter) else: formatter = '%(levelname)s: %(message)s' logging.basicConfig(level=logging.INFO, format=formatter) # check ADB AdbWrapper.check_adb() # assign the variable self.set_serial(args.serial) if args.gaia: if self._is_gaia_package(args.gaia): self.set_gaia(args.gaia) if args.gecko: if self._is_gecko_package(args.gecko): self.set_gecko(args.gecko) self.set_keep_profile(args.keep_profile) # return instance return self