diff --git a/wlauto/common/android/device.py b/wlauto/common/android/device.py index 35c8a79d..452dd1f8 100644 --- a/wlauto/common/android/device.py +++ b/wlauto/common/android/device.py @@ -30,7 +30,7 @@ from wlauto.common.resources import Executable from wlauto.core.resource import NO_ONE from wlauto.common.linux.device import BaseLinuxDevice, PsEntry from wlauto.exceptions import DeviceError, WorkerThreadError, TimeoutError, DeviceNotRespondingError -from wlauto.utils.misc import convert_new_lines, ABI_MAP +from wlauto.utils.misc import convert_new_lines, ABI_MAP, commonprefix from wlauto.utils.types import boolean, regex from wlauto.utils.android import (adb_shell, adb_background_shell, adb_list_devices, adb_command, AndroidProperties, ANDROID_VERSION_MAP) @@ -716,12 +716,33 @@ class AndroidDevice(BaseLinuxDevice): # pylint: disable=W0223 except KeyError: return None - def broadcast_media_mounted(self, dirpath): + def refresh_device_files(self, file_list): + """ + Depending on the devices 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.device.is_rooted or self.device.get_sdk_version() < 24: # MM and below + common_path = commonprefix(file_list, sep=self.device.path.sep) + self.broadcast_media_mounted(common_path, self.device.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) + command = 'am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://' + self.execute(command + dirpath, as_root=as_root) + # Internal methods: do not use outside of the class. diff --git a/wlauto/common/android/workload.py b/wlauto/common/android/workload.py index 7bc4ed55..fa2454ba 100755 --- a/wlauto/common/android/workload.py +++ b/wlauto/common/android/workload.py @@ -653,20 +653,26 @@ class AndroidUxPerfWorkload(AndroidUiAutoBenchmark): def push_assets(self, context): pushed = False + file_list = [] for f in self.deployable_assets: fpath = context.resolver.get(File(self, f)) device_path = self._path_on_device(fpath) if self.force_push_assets or not self.device.file_exists(device_path): self.device.push_file(fpath, device_path, timeout=300) + file_list.append(device_path) pushed = True if pushed: - self.device.broadcast_media_mounted(self.device.working_directory) + self.device.refresh_device_files(file_list) def delete_assets(self): if self.deployable_assets: + file_list = [] for f in self.deployable_assets: - self.device.delete_file(self._path_on_device(f)) - self.device.broadcast_media_mounted(self.device.working_directory) + f = self._path_on_device(f) + self.device.delete_file(f) + file_list.append(f) + self.device.delete_file(f) + self.device.refresh_device_files(file_list) def __init__(self, device, **kwargs): super(AndroidUxPerfWorkload, self).__init__(device, **kwargs) diff --git a/wlauto/utils/android.py b/wlauto/utils/android.py index affb8ade..8ed7bded 100644 --- a/wlauto/utils/android.py +++ b/wlauto/utils/android.py @@ -38,6 +38,9 @@ logger = logging.getLogger('android') # See: # http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels ANDROID_VERSION_MAP = { + 25: 'NOUGAT_MR1', + 24: 'NOUGAT', + 23: 'MARSHMALLOW', 22: 'LOLLIPOP_MR1', 21: 'LOLLIPOP', 20: 'KITKAT_WATCH', diff --git a/wlauto/utils/misc.py b/wlauto/utils/misc.py index 98e79e05..a66e985b 100644 --- a/wlauto/utils/misc.py +++ b/wlauto/utils/misc.py @@ -848,3 +848,16 @@ def memoized(func): return __memo_cache[id_string] return memoize_wrapper + + +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) diff --git a/wlauto/workloads/googlephotos/__init__.py b/wlauto/workloads/googlephotos/__init__.py index 4b6e2006..57c5030b 100755 --- a/wlauto/workloads/googlephotos/__init__.py +++ b/wlauto/workloads/googlephotos/__init__.py @@ -83,17 +83,22 @@ class Googlephotos(AndroidUxPerfWorkload): # This is to guarantee ordering and allows the workload to select a specific # image by subfolder, as filenames are not shown easily within the app d = self.device.working_directory + file_list = [] for i, f in enumerate(self.test_images): self.device.execute('mkdir -p {0}/wa-{1}'.format(d, i + 1)) self.device.execute('mv {0}/{2} {0}/wa-{1}/{2}'.format(d, i + 1, f)) + file_list.append('{0}/wa-{1}/{2}'.format(d, i + 1, f)) # Force rescan - self.device.broadcast_media_mounted(self.device.working_directory) + self.device.refresh_device_files(file_list) def teardown(self, context): super(Googlephotos, self).teardown(context) # Remove the subfolders and its content d = self.device.working_directory + file_list = [] for i in xrange(len(self.test_images)): - self.device.execute('rm -rf {0}/wa-{1}'.format(d, i + 1)) + f = '{0}/wa-{1}'.format(d, i + 1) + self.device.execute('rm -rf {}'.format(f)) + file_list.append(f) # Force rescan - self.device.broadcast_media_mounted(self.device.working_directory) + self.device.refresh_device_files(file_list)