Index: build/android/pylib/android_commands.py |
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py |
index f43fc4921795b4952ef64f0867c7bdd24d0a0d69..816b002479afe0dcc8913894189f4e5f823ef077 100644 |
--- a/build/android/pylib/android_commands.py |
+++ b/build/android/pylib/android_commands.py |
@@ -13,6 +13,7 @@ import datetime |
import inspect |
import logging |
import os |
+import random |
import re |
import shlex |
import signal |
@@ -78,6 +79,34 @@ CONTROL_USB_CHARGING_COMMANDS = [ |
}, |
] |
+class DeviceTempFile(object): |
+ def __init__(self, android_commands, prefix='temp_file', suffix=''): |
+ """Find an unused temporary file path in the devices external directory. |
+ |
+ When this object is closed, the file will be deleted on the device. |
+ """ |
+ self.android_commands = android_commands |
+ while True: |
+ # TODO(cjhopman): This could actually return the same file in multiple |
+ # calls if the caller doesn't write to the files immediately. This is |
+ # expected to never happen. |
+ i = random.randint(0, 1000000) |
+ self.name = '%s/%s-%d-%010d%s' % ( |
+ android_commands.GetExternalStorage(), |
+ prefix, int(time.time()), i, suffix) |
+ if not android_commands.FileExistsOnDevice(self.name): |
+ break |
+ |
+ def __enter__(self): |
+ return self |
+ |
+ def __exit__(self, type, value, traceback): |
+ self.close() |
+ |
+ def close(self): |
+ self.android_commands.RunShellCommand('rm ' + self.name) |
+ |
+ |
def GetAVDs(): |
"""Returns a list of AVDs.""" |
re_avd = re.compile('^[ ]+Name: ([a-zA-Z0-9_:.-]+)', re.MULTILINE) |
@@ -1125,16 +1154,6 @@ class AndroidCommands(object): |
f.flush() |
self._adb.Push(f.name, filename) |
- _TEMP_FILE_BASE_FMT = 'temp_file_%d' |
- _TEMP_SCRIPT_FILE_BASE_FMT = 'temp_script_file_%d.sh' |
- |
- def _GetDeviceTempFileName(self, base_name): |
- i = 0 |
- while self.FileExistsOnDevice( |
- self.GetExternalStorage() + '/' + base_name % i): |
- i += 1 |
- return self.GetExternalStorage() + '/' + base_name % i |
- |
def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False): |
return self.RunShellCommand('su -c %s' % command, timeout_time, log_result) |
@@ -1192,27 +1211,22 @@ class AndroidCommands(object): |
This is less efficient than SetFileContents. |
""" |
- temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE_FMT) |
- temp_script = self._GetDeviceTempFileName( |
- AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) |
+ with DeviceTempFile(self) as temp_file: |
+ with DeviceTempFile(self, suffix=".sh") as temp_script: |
+ # Put the contents in a temporary file |
+ self.SetFileContents(temp_file.name, contents) |
+ # Create a script to copy the file contents to its final destination |
+ self.SetFileContents(temp_script.name, |
+ 'cat %s > %s' % (temp_file.name, filename)) |
+ |
+ command = 'sh %s' % temp_script.name |
+ command_runner = self._GetProtectedFileCommandRunner() |
+ if command_runner: |
+ return command_runner(command) |
+ else: |
+ logging.warning( |
+ 'Could not set contents of protected file: %s' % filename) |
- try: |
- # Put the contents in a temporary file |
- self.SetFileContents(temp_file, contents) |
- # Create a script to copy the file contents to its final destination |
- self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) |
- |
- command = 'sh %s' % temp_script |
- command_runner = self._GetProtectedFileCommandRunner() |
- if command_runner: |
- return command_runner(command) |
- else: |
- logging.warning( |
- 'Could not set contents of protected file: %s' % filename) |
- finally: |
- # And remove the temporary files |
- self.RunShellCommand('rm ' + temp_file) |
- self.RunShellCommand('rm ' + temp_script) |
def RemovePushedFiles(self): |
"""Removes all files pushed with PushIfNeeded() from the device.""" |
@@ -1877,28 +1891,23 @@ class AndroidCommands(object): |
dest: absolute path of destination directory |
""" |
logging.info('In EfficientDeviceDirectoryCopy %s %s', source, dest) |
- temp_script_file = self._GetDeviceTempFileName( |
- AndroidCommands._TEMP_SCRIPT_FILE_BASE_FMT) |
- host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, |
- 'build', |
- 'android', |
- 'pylib', |
- 'efficient_android_directory_copy.sh') |
- try: |
- self._adb.Push(host_script_path, temp_script_file) |
- self.EnableAdbRoot() |
- out = self.RunShellCommand('sh %s %s %s' % (temp_script_file, |
- source, |
- dest), |
- timeout_time=120) |
+ with DeviceTempFile(self, suffix=".sh") as temp_script_file: |
+ host_script_path = os.path.join(constants.DIR_SOURCE_ROOT, |
+ 'build', |
+ 'android', |
+ 'pylib', |
+ 'efficient_android_directory_copy.sh') |
+ self._adb.Push(host_script_path, temp_script_file.name) |
+ self.EnableAdbRoot |
+ out = self.RunShellCommand( |
+ 'sh %s %s %s' % (temp_script_file.name, source, dest), |
+ timeout_time=120) |
if self._device: |
device_repr = self._device[-4:] |
else: |
device_repr = '????' |
for line in out: |
logging.info('[%s]> %s', device_repr, line) |
- finally: |
- self.RunShellCommand('rm %s' % temp_script_file) |
def _GetControlUsbChargingCommand(self): |
if self._control_usb_charging_command['cached']: |