Do not crash upon adb logcat clear error. (#501)
diff --git a/mobly/controllers/android_device.py b/mobly/controllers/android_device.py
index 472e0d7..72f0848 100644
--- a/mobly/controllers/android_device.py
+++ b/mobly/controllers/android_device.py
@@ -447,8 +447,7 @@
# logging.log_path only exists when this is used in an Mobly test run.
self._log_path_base = getattr(logging, 'log_path', '/tmp/logs')
self._log_path = os.path.join(
- self._log_path_base,
- 'AndroidDevice%s' % self._normalized_serial)
+ self._log_path_base, 'AndroidDevice%s' % self._normalized_serial)
self._debug_tag = self._serial
self.log = AndroidDeviceLoggerAdapter(logging.getLogger(), {
'tag': self.debug_tag
@@ -1035,7 +1034,16 @@
self,
'Logcat thread is already running, cannot start another one.')
if clear_log:
- self._clear_adb_log()
+ try:
+ self._clear_adb_log()
+ except adb.AdbError as e:
+ # On Android O, the clear command fails due to a known bug.
+ # Catching this so we don't crash from this Android issue.
+ if "failed to clear" in e.stderr:
+ self.log.warning(
+ 'Encountered known Android error to clear logcat.')
+ else:
+ raise
self._enable_logpersist()
diff --git a/tests/mobly/controllers/android_device_test.py b/tests/mobly/controllers/android_device_test.py
index 093be61..d3221a4 100755
--- a/tests/mobly/controllers/android_device_test.py
+++ b/tests/mobly/controllers/android_device_test.py
@@ -460,6 +460,40 @@
@mock.patch(
'mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device.AndroidDevice._clear_adb_log')
+ def test_AndroidDevice_start_adb_logcat_clear_log_fails(
+ self, mock_clear_adb_log, stop_proc_mock, start_proc_mock,
+ creat_dir_mock, FastbootProxy, MockAdbProxy):
+ """Verifies the steps of collecting adb logcat on an AndroidDevice
+ object, including various function calls and the expected behaviors of
+ the calls.
+ """
+ mock_clear_adb_log.side_effect = adb.AdbError(
+ cmd='adb -s xx logcat -c',
+ stdout='',
+ stderr="failed to clear 'main' log",
+ ret_code=1)
+ mock_serial = '1'
+ ad = android_device.AndroidDevice(serial=mock_serial)
+ ad.start_adb_logcat()
+ # Verify start did the correct operations.
+ self.assertTrue(ad._adb_logcat_process)
+ expected_log_path = os.path.join(logging.log_path,
+ 'AndroidDevice%s' % ad.serial,
+ 'adblog,fakemodel,%s.txt' % ad.serial)
+ creat_dir_mock.assert_called_with(os.path.dirname(expected_log_path))
+
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch('mobly.utils.create_dir')
+ @mock.patch(
+ 'mobly.utils.start_standing_subprocess', return_value='process')
+ @mock.patch('mobly.utils.stop_standing_subprocess')
def test_AndroidDevice_take_logcat_with_user_param(
self, stop_proc_mock, start_proc_mock, creat_dir_mock,
FastbootProxy, MockAdbProxy):