OLD | NEW |
---|---|
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Provides an interface to communicate with the device via the adb command. | 5 """Provides an interface to communicate with the device via the adb command. |
6 | 6 |
7 Assumes adb binary is currently on system path. | 7 Assumes adb binary is currently on system path. |
8 """ | 8 """ |
9 | 9 |
10 import collections | 10 import collections |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 files = {} | 143 files = {} |
144 for line in ls_output: | 144 for line in ls_output: |
145 directory_match = re_directory.match(line) | 145 directory_match = re_directory.match(line) |
146 if directory_match: | 146 if directory_match: |
147 current_dir = directory_match.group('dir') | 147 current_dir = directory_match.group('dir') |
148 continue | 148 continue |
149 file_match = re_file.match(line) | 149 file_match = re_file.match(line) |
150 if file_match: | 150 if file_match: |
151 filename = os.path.join(current_dir, file_match.group('filename')) | 151 filename = os.path.join(current_dir, file_match.group('filename')) |
152 if filename.startswith(path_dir): | 152 if filename.startswith(path_dir): |
153 filename = filename[len(path_dir)+1:] | 153 filename = filename[len(path_dir) + 1:] |
154 lastmod = datetime.datetime.strptime( | 154 lastmod = datetime.datetime.strptime( |
155 file_match.group('date') + ' ' + file_match.group('time')[:5], | 155 file_match.group('date') + ' ' + file_match.group('time')[:5], |
156 '%Y-%m-%d %H:%M') | 156 '%Y-%m-%d %H:%M') |
157 if not utc_offset and 'timezone' in re_file.groupindex: | 157 if not utc_offset and 'timezone' in re_file.groupindex: |
158 utc_offset = file_match.group('timezone') | 158 utc_offset = file_match.group('timezone') |
159 if isinstance(utc_offset, str) and len(utc_offset) == 5: | 159 if isinstance(utc_offset, str) and len(utc_offset) == 5: |
160 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]), | 160 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]), |
161 minutes=int(utc_offset[3:5])) | 161 minutes=int(utc_offset[3:5])) |
162 if utc_offset[0:1] == '-': | 162 if utc_offset[0:1] == '-': |
163 utc_delta = -utc_delta | 163 utc_delta = -utc_delta |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 root_test_output = self.RunShellCommand('ls /root') or [''] | 219 root_test_output = self.RunShellCommand('ls /root') or [''] |
220 return not 'Permission denied' in root_test_output[0] | 220 return not 'Permission denied' in root_test_output[0] |
221 | 221 |
222 def EnableAdbRoot(self): | 222 def EnableAdbRoot(self): |
223 """Enables adb root on the device. | 223 """Enables adb root on the device. |
224 | 224 |
225 Returns: | 225 Returns: |
226 True: if output from executing adb root was as expected. | 226 True: if output from executing adb root was as expected. |
227 False: otherwise. | 227 False: otherwise. |
228 """ | 228 """ |
229 return_value = self._adb.EnableAdbRoot() | 229 if self.GetBuildType() == 'user': |
230 # EnableAdbRoot inserts a call for wait-for-device only when adb logcat | 230 logging.warning("Can't enable root in production builds with type user") |
231 # output matches what is expected. Just to be safe add a call to | 231 return False |
232 # wait-for-device. | 232 else: |
233 self._adb.SendCommand('wait-for-device') | 233 return_value = self._adb.EnableAdbRoot() |
234 return return_value | 234 # EnableAdbRoot inserts a call for wait-for-device only when adb logcat |
235 # output matches what is expected. Just to be safe add a call to | |
236 # wait-for-device. | |
237 self._adb.SendCommand('wait-for-device') | |
238 return return_value | |
235 | 239 |
236 def GetDeviceYear(self): | 240 def GetDeviceYear(self): |
237 """Returns the year information of the date on device.""" | 241 """Returns the year information of the date on device.""" |
238 return self.RunShellCommand('date +%Y')[0] | 242 return self.RunShellCommand('date +%Y')[0] |
239 | 243 |
240 def GetExternalStorage(self): | 244 def GetExternalStorage(self): |
241 if not self._external_storage: | 245 if not self._external_storage: |
242 self._external_storage = self.RunShellCommand('echo $EXTERNAL_STORAGE')[0] | 246 self._external_storage = self.RunShellCommand('echo $EXTERNAL_STORAGE')[0] |
243 assert self._external_storage, 'Unable to find $EXTERNAL_STORAGE' | 247 assert self._external_storage, 'Unable to find $EXTERNAL_STORAGE' |
244 return self._external_storage | 248 return self._external_storage |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
321 | 325 |
322 install_cmd = ['install'] | 326 install_cmd = ['install'] |
323 | 327 |
324 if reinstall: | 328 if reinstall: |
325 install_cmd.append('-r') | 329 install_cmd.append('-r') |
326 | 330 |
327 install_cmd.append(package_file_path) | 331 install_cmd.append(package_file_path) |
328 install_cmd = ' '.join(install_cmd) | 332 install_cmd = ' '.join(install_cmd) |
329 | 333 |
330 logging.info('>>> $' + install_cmd) | 334 logging.info('>>> $' + install_cmd) |
331 return self._adb.SendCommand(install_cmd, timeout_time=2*60, retry_count=0) | 335 return self._adb.SendCommand(install_cmd, |
336 timeout_time=2 * 60, | |
337 retry_count=0) | |
332 | 338 |
333 def ManagedInstall(self, apk_path, keep_data=False, package_name=None, | 339 def ManagedInstall(self, apk_path, keep_data=False, package_name=None, |
334 reboots_on_failure=2): | 340 reboots_on_failure=2): |
335 """Installs specified package and reboots device on timeouts. | 341 """Installs specified package and reboots device on timeouts. |
336 | 342 |
337 Args: | 343 Args: |
338 apk_path: Path to .apk file to install. | 344 apk_path: Path to .apk file to install. |
339 keep_data: Reinstalls instead of uninstalling first, preserving the | 345 keep_data: Reinstalls instead of uninstalling first, preserving the |
340 application data. | 346 application data. |
341 package_name: Package name (only needed if keep_data=False). | 347 package_name: Package name (only needed if keep_data=False). |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 assert os.path.exists(local_path), 'Local path not found %s' % local_path | 635 assert os.path.exists(local_path), 'Local path not found %s' % local_path |
630 hashes_on_host = _ComputeFileListHash( | 636 hashes_on_host = _ComputeFileListHash( |
631 subprocess.Popen( | 637 subprocess.Popen( |
632 '%s_host %s' % (self._md5sum_path, local_path), | 638 '%s_host %s' % (self._md5sum_path, local_path), |
633 stdout=subprocess.PIPE, shell=True).stdout) | 639 stdout=subprocess.PIPE, shell=True).stdout) |
634 if hashes_on_device == hashes_on_host: | 640 if hashes_on_device == hashes_on_host: |
635 return | 641 return |
636 | 642 |
637 # They don't match, so remove everything first and then create it. | 643 # They don't match, so remove everything first and then create it. |
638 if os.path.isdir(local_path): | 644 if os.path.isdir(local_path): |
639 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2*60) | 645 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2 * 60) |
640 self.RunShellCommand('mkdir -p %s' % device_path) | 646 self.RunShellCommand('mkdir -p %s' % device_path) |
641 | 647 |
642 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of | 648 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of |
643 # 60 seconds which isn't sufficient for a lot of users of this method. | 649 # 60 seconds which isn't sufficient for a lot of users of this method. |
644 push_command = 'push %s %s' % (local_path, device_path) | 650 push_command = 'push %s %s' % (local_path, device_path) |
645 logging.info('>>> $' + push_command) | 651 logging.info('>>> $' + push_command) |
646 output = self._adb.SendCommand(push_command, timeout_time=30*60) | 652 output = self._adb.SendCommand(push_command, timeout_time=30 * 60) |
647 assert _HasAdbPushSucceeded(output) | 653 assert _HasAdbPushSucceeded(output) |
648 | 654 |
649 | 655 |
650 def GetFileContents(self, filename, log_result=False): | 656 def GetFileContents(self, filename, log_result=False): |
651 """Gets contents from the file specified by |filename|.""" | 657 """Gets contents from the file specified by |filename|.""" |
652 return self.RunShellCommand('if [ -f "' + filename + '" ]; then cat "' + | 658 return self.RunShellCommand('if [ -f "' + filename + '" ]; then cat "' + |
653 filename + '"; fi', log_result=log_result) | 659 filename + '"; fi', log_result=log_result) |
654 | 660 |
655 def SetFileContents(self, filename, contents): | 661 def SetFileContents(self, filename, contents): |
656 """Writes |contents| to the file specified by |filename|.""" | 662 """Writes |contents| to the file specified by |filename|.""" |
657 with tempfile.NamedTemporaryFile() as f: | 663 with tempfile.NamedTemporaryFile() as f: |
658 f.write(contents) | 664 f.write(contents) |
659 f.flush() | 665 f.flush() |
660 self._adb.Push(f.name, filename) | 666 self._adb.Push(f.name, filename) |
661 | 667 |
668 _TEMP_FILE_BASE = 'temp_file_%d' | |
669 _TEMP_SCRIPT_FILE_BASE = 'temp_script_file_%d.sh' | |
670 | |
671 def _GetDeviceTempFileName(self, base_name): | |
672 i = 0 | |
673 while self.FileExistsOnDevice( | |
674 self.GetExternalStorage() + '/' + base_name % i): | |
bulach
2013/01/16 19:11:05
since base_name is required to be a format and thi
aberent
2013/01/17 17:18:06
Will add format, but can't use _TEMP_FILE_BASE(_FM
| |
675 i += 1 | |
676 return self.GetExternalStorage() + '/' + base_name % i | |
677 | |
678 def SetProtectedFileContents(self, filename, contents): | |
679 """Writes |contents| to the file specified by |filename|. | |
bulach
2013/01/16 19:11:05
nit: add a \n (python style requires a one-line do
aberent
2013/01/17 17:18:06
Done.
| |
680 This is less efficient than SetFileContents, but will | |
681 work for protected files and device files.""" | |
682 temp_file = self._GetDeviceTempFileName(AndroidCommands._TEMP_FILE_BASE) | |
683 temp_script = self._GetDeviceTempFileName( | |
684 AndroidCommands._TEMP_SCRIPT_FILE_BASE) | |
685 | |
686 # Put the contents in a temporary file | |
687 self.SetFileContents(temp_file, contents) | |
688 # Create a script to copy the file contents to its final destination | |
689 self.SetFileContents(temp_script, 'cat %s > %s' % (temp_file, filename)) | |
690 # Run the script as root | |
691 self.RunShellCommand('su -c sh %s' % temp_script) | |
692 # And remove the temporary files | |
693 self.RunShellCommand('rm ' + temp_file) | |
694 self.RunShellCommand('rm ' + temp_script) | |
695 | |
662 def RemovePushedFiles(self): | 696 def RemovePushedFiles(self): |
663 """Removes all files pushed with PushIfNeeded() from the device.""" | 697 """Removes all files pushed with PushIfNeeded() from the device.""" |
664 for p in self._pushed_files: | 698 for p in self._pushed_files: |
665 self.RunShellCommand('rm -r %s' % p, timeout_time=2*60) | 699 self.RunShellCommand('rm -r %s' % p, timeout_time=2 * 60) |
666 | 700 |
667 def ListPathContents(self, path): | 701 def ListPathContents(self, path): |
668 """Lists files in all subdirectories of |path|. | 702 """Lists files in all subdirectories of |path|. |
669 | 703 |
670 Args: | 704 Args: |
671 path: The path to list. | 705 path: The path to list. |
672 | 706 |
673 Returns: | 707 Returns: |
674 A dict of {"name": (size, lastmod), ...}. | 708 A dict of {"name": (size, lastmod), ...}. |
675 """ | 709 """ |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1110 """ | 1144 """ |
1111 def __init__(self, output): | 1145 def __init__(self, output): |
1112 self._output = output | 1146 self._output = output |
1113 | 1147 |
1114 def write(self, data): | 1148 def write(self, data): |
1115 data = data.replace('\r\r\n', '\n') | 1149 data = data.replace('\r\r\n', '\n') |
1116 self._output.write(data) | 1150 self._output.write(data) |
1117 | 1151 |
1118 def flush(self): | 1152 def flush(self): |
1119 self._output.flush() | 1153 self._output.flush() |
OLD | NEW |