Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 249 lines (236 sloc) 13.4 KB
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at
import re
import os
import json
import shutil
import zipfile
import tempfile
import argparse
import subprocess
from distutils import util
from datetime import datetime
from argparse import ArgumentDefaultsHelpFormatter
from utilities import console_utilities
from utilities.adb_helper import AdbHelper
class VersionChecker(object):
def __init__(self, **kwargs):
self.arg_parser = argparse.ArgumentParser(description='Check the version information of Firefox OS.',
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.args = self.arg_parser.parse_args()
def get_device_info(self, serial=None):
tmp_dir = tempfile.mkdtemp(prefix='checkversions_')
# pull data from device
if not AdbHelper.adb_pull('/system/b2g/omni.ja', tmp_dir, serial=serial):
print 'Error pulling Gecko file.'
if not AdbHelper.adb_pull('/data/local/webapps/', tmp_dir, serial=serial):
if not AdbHelper.adb_pull('/system/b2g/webapps/', tmp_dir, serial=serial):
print 'Error pulling Gaia file.'
if not AdbHelper.adb_pull('/system/b2g/application.ini', tmp_dir, serial=serial):
print 'Error pulling application.ini file.'
# get Gaia info
gaia_rev = 'n/a'
gaia_date = 'n/a'
application_zip_file = tmp_dir + os.sep + ''
if os.path.isfile(application_zip_file):
f = open(application_zip_file, 'rb')
z = zipfile.ZipFile(f)
z.extract('resources/gaia_commit.txt', tmp_dir)
print 'Can not find file.'
gaiacommit_file = tmp_dir + os.sep + 'resources/gaia_commit.txt'
if os.path.isfile(gaiacommit_file):
f = open(gaiacommit_file, "r")
gaia_rev = re.sub(r'\n+', '', f.readline())
gaia_date_sec_from_epoch = re.sub(r'\n+', '', f.readline())
gaia_date = datetime.utcfromtimestamp(int(gaia_date_sec_from_epoch)).strftime('%Y-%m-%d %H:%M:%S')
print 'Can not get gaia_commit.txt file from file.'
# deoptimize omni.ja for Gecko info
gecko_rev = 'n/a'
if os.path.isfile(tmp_dir + os.sep + 'omni.ja'):
deopt_dir = tmp_dir + os.sep + 'deopt'
deopt_file = deopt_dir + os.sep + 'omni.ja'
deopt_exec = tmp_dir + os.sep + ''
shutil.copyfile('./', deopt_exec)
cmd = 'python %s --deoptimize %s %s %s' % (deopt_exec, tmp_dir, tmp_dir, deopt_dir)
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.communicate()[0]
# unzip omni.ja to get Gecko info
if os.path.isfile(deopt_file):
f = open(deopt_file, 'rb')
z = zipfile.ZipFile(f)
z.extract('chrome/toolkit/content/global/buildconfig.html', tmp_dir)
print 'Can not deoptimize omni.ja file.'
gecko_rev = 'n/a'
# get Gecko info from buildconfig.html file
buildconfig_file = tmp_dir + os.sep + 'chrome/toolkit/content/global/buildconfig.html'
if os.path.isfile(buildconfig_file):
for line in open(buildconfig_file, "r"):
if'Built from', line):
ret = re.findall(r'>(.*?)<', line)
gecko_rev = ret[1]
print 'Can not get buildconfig.html file from omni.ja file.'
print 'Can not find omni.ja file.'
# get Gecko version, and B2G BuildID from application.ini file
if os.path.isfile(tmp_dir + os.sep + 'application.ini'):
for line in open(tmp_dir + os.sep + 'application.ini', "r"):
if'^\s*BuildID', line):
ret = re.findall(r'.*?=(.*)', line)
build_id = ret[0]
if'^\s*Version', line):
ret = re.findall(r'.*?=(.*)', line)
version = ret[0]
build_id = 'n/a'
version = 'n/a'
# get device information by getprop command
device_name = re.sub(r'\r+|\n+', '', AdbHelper.adb_shell('getprop ro.product.device', serial=serial))
firmware_release = re.sub(r'\r+|\n+', '', AdbHelper.adb_shell('getprop', serial=serial))
firmware_incremental = re.sub(r'\r+|\n+', '', AdbHelper.adb_shell('getprop', serial=serial))
firmware_date = re.sub(r'\r+|\n+', '', AdbHelper.adb_shell('getprop', serial=serial))
firmware_bootloader = re.sub(r'\r+|\n+', '', AdbHelper.adb_shell('getprop ro.boot.bootloader', serial=serial))
# prepare the return information
device_info = {}
device_info['Serial'] = serial
device_info['Build ID'] = build_id
device_info['Gaia Revision'] = gaia_rev
device_info['Gaia Date'] = gaia_date
device_info['Gecko Revision'] = gecko_rev
device_info['Gecko Version'] = version
device_info['Device Name'] = device_name
device_info['Firmware(Release)'] = firmware_release
device_info['Firmware(Incremental)'] = firmware_incremental
device_info['Firmware Date'] = firmware_date
device_info['Bootloader'] = firmware_bootloader
return device_info
def _print_device_info_item(self, title, value, title_color=None, value_color=None):
console_utilities.print_color('{0:22s}'.format(title), fg_color=title_color, newline=False)
console_utilities.print_color(value, fg_color=value_color)
def print_device_info(self, device_info, no_color=False):
# setup the format by platform
if no_color:
title_color = None
sw_color = None
hw_color = None
title_color = console_utilities.COLOR_LIGHT_BLUE
sw_color = console_utilities.COLOR_LIGHT_GREEN
hw_color = console_utilities.COLOR_LIGHT_YELLOW
# print the device information
self._print_device_info_item('Build ID', device_info['Build ID'], title_color=title_color, value_color=sw_color)
self._print_device_info_item('Gaia Revision', device_info['Gaia Revision'], title_color=title_color, value_color=sw_color)
self._print_device_info_item('Gaia Date', device_info['Gaia Date'], title_color=title_color, value_color=sw_color)
self._print_device_info_item('Gecko Revision', device_info['Gecko Revision'], title_color=title_color, value_color=sw_color)
self._print_device_info_item('Gecko Version', device_info['Gecko Version'], title_color=title_color, value_color=sw_color)
self._print_device_info_item('Device Name', device_info['Device Name'], title_color=title_color, value_color=hw_color)
self._print_device_info_item('Firmware(Release)', device_info['Firmware(Release)'], title_color=title_color, value_color=hw_color)
self._print_device_info_item('Firmware(Incremental)', device_info['Firmware(Incremental)'], title_color=title_color, value_color=hw_color)
self._print_device_info_item('Firmware Date', device_info['Firmware Date'], title_color=title_color, value_color=hw_color)
if device_info['Bootloader'] is not '':
self._print_device_info_item('Bootloader', device_info['Bootloader'], title_color=title_color, value_color=hw_color)
print ''
def output_log(self, device_info_list):
if self.args.log_json is None and self.args.log_text is None:
# prepare the result dict for parsing
result = {}
unknown_serial_index = 1
for device_info in device_info_list:
if device_info['Serial'] == None:
device_serial = 'unknown_serial_' + str(unknown_serial_index)
unknown_serial_index = unknown_serial_index + 1
device_serial = device_info['Serial']
result[device_serial] = device_info
# output
if self.args.log_text is not None:
with open(self.args.log_text, 'w') as outfile:
for device_serial, device_info in result.items():
outfile.write('# %s\n' % device_serial)
if 'Skip' in device_info and device_info['Skip'] is True:
outfile.write('%s=%s\n' % ('Skip', device_info['Skip']))
for key, value in device_info.items():
outfile.write('%s=%s\n' % (re.sub(r'\s+|\(|\)', '', key), re.sub(r'\s+', '_', value)))
if self.args.log_json is not None:
with open(self.args.log_json, 'w') as outfile:
json.dump(result, outfile, indent=4)
def run(self):
devices = AdbHelper.adb_devices()
is_no_color = self.args.no_color
if 'NO_COLOR' in os.environ:
is_no_color = bool(util.strtobool(os.environ['NO_COLOR'].lower()))
print 'Invalid NO_COLOR value [{0}].'.format(os.environ['NO_COLOR'])
if len(devices) == 0:
print 'No device.'
elif len(devices) >= 1:
# has --serial, then skip ANDROID_SERIAL, then list one device by --serial
if (self.args.serial is not None):
if self.args.serial in devices:
serial = self.args.serial
print 'Serial: {0} (State: {1})'.format(serial, devices[serial])
device_info = self.get_device_info(serial=serial)
self.print_device_info(device_info, no_color=is_no_color)
print 'Can not found {0}.\nDevices:'.format(self.args.serial)
for device, state in devices.items():
print 'Serial: {0} (State: {1})'.format(device, state)
# no --serial, but has ANDROID_SERIAL, then list one device by ANDROID_SERIAL
elif (self.args.serial is None) and ('ANDROID_SERIAL' in os.environ):
if os.environ['ANDROID_SERIAL'] in devices:
serial = os.environ['ANDROID_SERIAL']
print 'Serial: {0} (State: {1})'.format(serial, devices[serial])
device_info = self.get_device_info(serial=serial)
self.print_device_info(device_info, no_color=is_no_color)
print 'Can not found {0}.\nDevices:'.format(os.environ['ANDROID_SERIAL'])
for device, state in devices.items():
print 'Serial: {0} (State: {1})'.format(device, state)
# no --serial, no ANDROID_SERIAL, then list all devices
if (self.args.serial is None) and (not 'ANDROID_SERIAL' in os.environ):
if len(devices) > 1:
print 'More than one device.'
print 'You can specify ANDROID_SERIAL by "--serial" option.\n'
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)
print 'Skipped.\n'
device_info_list.append({'Serial': device, 'Skip': True})
if __name__ == "__main__":
if not AdbHelper.has_adb():
print 'There is no "adb" in your environment PATH.'
my_app = VersionChecker()
You can’t perform that action at this time.