1
0
mirror of https://github.com/ARM-software/devlib.git synced 2025-04-18 15:50:04 +01:00

Merge pull request #201 from marcbonnici/android

Android
This commit is contained in:
setrofim 2017-11-14 13:51:36 +00:00 committed by GitHub
commit 4ef1e51b97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 3 deletions

View File

@ -15,8 +15,9 @@ from devlib.platform import Platform
from devlib.exception import TargetError, TargetNotRespondingError, TimeoutError from devlib.exception import TargetError, TargetNotRespondingError, TimeoutError
from devlib.utils.ssh import SshConnection from devlib.utils.ssh import SshConnection
from devlib.utils.android import AdbConnection, AndroidProperties, LogcatMonitor, adb_command, adb_disconnect from devlib.utils.android import AdbConnection, AndroidProperties, LogcatMonitor, adb_command, adb_disconnect
from devlib.utils.misc import memoized, isiterable, convert_new_lines, merge_lists from devlib.utils.misc import memoized, isiterable, convert_new_lines
from devlib.utils.misc import ABI_MAP, get_cpu_name, ranges_to_list, escape_double_quotes from devlib.utils.misc import commonprefix, escape_double_quotes, merge_lists
from devlib.utils.misc import ABI_MAP, get_cpu_name, ranges_to_list
from devlib.utils.types import integer, boolean, bitmask, identifier, caseless_string from devlib.utils.types import integer, boolean, bitmask, identifier, caseless_string
@ -486,7 +487,7 @@ class Target(object):
raise IOError('No usable temporary filename found') raise IOError('No usable temporary filename found')
def remove(self, path, as_root=False): def remove(self, path, as_root=False):
self.execute('rm -rf {}'.format(path), as_root=as_root) self.execute('rm -rf "{}"'.format(escape_double_quotes(path)), as_root=as_root)
# misc # misc
def core_cpus(self, core): def core_cpus(self, core):
@ -957,6 +958,11 @@ class AndroidTarget(Target):
except KeyError: except KeyError:
return None return None
@property
@memoized
def external_storage(self):
return self.execute('echo $EXTERNAL_STORAGE').strip()
@property @property
@memoized @memoized
def screen_resolution(self): def screen_resolution(self):
@ -1195,6 +1201,46 @@ class AndroidTarget(Target):
else: else:
raise TargetError('Can\'t install {}: unsupported format.'.format(filepath)) raise TargetError('Can\'t install {}: unsupported format.'.format(filepath))
def grant_package_permission(self, package, permission):
try:
return self.execute('pm grant {} {}'.format(package, permission))
except TargetError as e:
if 'is not a changeable permission type' in e.message:
pass # Ignore if unchangeable
elif 'Unknown permission' in e.message:
pass # Ignore if unknown
elif 'has not requested permission' in e.message:
pass # Ignore if not requested
else:
raise
def refresh_files(self, file_list):
"""
Depending on the android version and root status, determine the
appropriate method of forcing a re-index of the mediaserver cache for a given
list of files.
"""
if self.is_rooted or self.get_sdk_version() < 24: # MM and below
common_path = commonprefix(file_list, sep=self.path.sep)
self.broadcast_media_mounted(common_path, self.is_rooted)
else:
for f in file_list:
self.broadcast_media_scan_file(f)
def broadcast_media_scan_file(self, filepath):
"""
Force a re-index of the mediaserver cache for the specified file.
"""
command = 'am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://'
self.execute(command + filepath)
def broadcast_media_mounted(self, dirpath, as_root=False):
"""
Force a re-index of the mediaserver cache for the specified directory.
"""
command = 'am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://'
self.execute(command + dirpath, as_root=as_root)
def install_executable(self, filepath, with_name=None): def install_executable(self, filepath, with_name=None):
self._ensure_executables_directory_is_writable() self._ensure_executables_directory_is_writable()
executable_name = with_name or os.path.basename(filepath) executable_name = with_name or os.path.basename(filepath)

View File

@ -121,6 +121,7 @@ class ApkInfo(object):
version_regex = re.compile(r"name='(?P<name>[^']+)' versionCode='(?P<vcode>[^']+)' versionName='(?P<vname>[^']+)'") version_regex = re.compile(r"name='(?P<name>[^']+)' versionCode='(?P<vcode>[^']+)' versionName='(?P<vname>[^']+)'")
name_regex = re.compile(r"name='(?P<name>[^']+)'") name_regex = re.compile(r"name='(?P<name>[^']+)'")
permission_regex = re.compile(r"name='(?P<permission>[^']+)'")
def __init__(self, path=None): def __init__(self, path=None):
self.path = path self.path = path
@ -130,6 +131,7 @@ class ApkInfo(object):
self.version_name = None self.version_name = None
self.version_code = None self.version_code = None
self.native_code = None self.native_code = None
self.permissions = []
self.parse(path) self.parse(path)
def parse(self, apk_path): def parse(self, apk_path):
@ -166,6 +168,10 @@ class ApkInfo(object):
if not found: if not found:
mapped_abis.append(apk_abi) mapped_abis.append(apk_abi)
self.native_code = mapped_abis self.native_code = mapped_abis
elif line.startswith('uses-permission:'):
match = self.permission_regex.search(line)
if match:
self.permissions.append(match.group('permission'))
else: else:
pass # not interested pass # not interested

View File

@ -445,6 +445,19 @@ def as_relative(path):
return path.lstrip(os.sep) return path.lstrip(os.sep)
def commonprefix(file_list, sep=os.sep):
"""
Find the lowest common base folder of a passed list of files.
"""
common_path = os.path.commonprefix(file_list)
cp_split = common_path.split(sep)
other_split = file_list[0].split(sep)
last = len(cp_split) - 1
if cp_split[last] != other_split[last]:
cp_split = cp_split[:-1]
return sep.join(cp_split)
def get_cpu_mask(cores): def get_cpu_mask(cores):
"""Return a string with the hex for the cpu mask for the specified core numbers.""" """Return a string with the hex for the cpu mask for the specified core numbers."""
mask = 0 mask = 0