| 37 | |
| 38 | |
| 39 | class Driver(object): |
| 40 | __instance = None |
| 41 | |
| 42 | @staticmethod |
| 43 | def instance(device): |
| 44 | if not Driver.__instance: |
| 45 | Driver.__instance = Driver(device) |
| 46 | return Driver.__instance |
| 47 | |
| 48 | """Helper class to execute shell commands on an Android device.""" |
| 49 | def __init__(self, device=None): |
| 50 | assert os.path.exists(ANDROID_DIR) |
| 51 | sys.path.insert(0, ANDROID_DIR) |
| 52 | |
| 53 | # We import the dependencies only on demand, so that this file can be |
| 54 | # imported unconditionally. |
| 55 | import devil_chromium |
| 56 | from devil.android import device_errors # pylint: disable=import-error |
| 57 | from devil.android import device_utils # pylint: disable=import-error |
| 58 | from devil.android.perf import cache_control # pylint: disable=import-error |
| 59 | from devil.android.perf import perf_control # pylint: disable=import-error |
| 60 | global cache_control |
| 61 | global device_errors |
| 62 | global perf_control |
| 63 | |
| 64 | devil_chromium.Initialize() |
| 65 | |
| 66 | # Find specified device or a single attached device if none was specified. |
| 67 | # In case none or multiple devices are attached, this raises an exception. |
| 68 | self.device = device_utils.DeviceUtils.HealthyDevices( |
| 69 | retries=5, enable_usb_resets=True, device_arg=device, |
| 70 | persistent_shell=False)[0] |
| 71 | |
| 72 | # Retrieve device parameters. |
| 73 | product_prop = 'getprop ro.build.product' |
| 74 | self.device_type = self.device.adb.Shell(product_prop).rstrip('\n') |
| 75 | assert self.device_type, 'No device type found in android environment.' |
| 76 | |
| 77 | # This remembers what we have already pushed to the device. |
| 78 | self.pushed = set() |
| 79 | |
| 80 | def tear_down(self): |
| 81 | """Clean up files after running all tests.""" |
| 82 | self.device.RemovePath(DEVICE_DIR, force=True, recursive=True) |
| 83 | |
| 84 | def push_file(self, host_dir, file_name, target_rel='.', |
| 85 | skip_if_missing=False): |
| 86 | """Push a single file to the device (cached). |
| 87 | |
| 88 | Args: |
| 89 | host_dir: Absolute parent directory of the file to push. |
| 90 | file_name: Name of the file to push. |
| 91 | target_rel: Parent directory of the target location on the device |
| 92 | (relative to the device's base dir for testing). |
| 93 | skip_if_missing: Keeps silent about missing files when set. Otherwise logs |
| 94 | error. |
| 95 | """ |
| 96 | # TODO(sergiyb): Implement this method using self.device.PushChangedFiles to |