bluetooth: add btmon log for raspberry pi and DUT
- Capture the btmon logs in both raspberry pi and DUT.
- Modify the cleanup logic in bluetooth_adapter_tests.py.
The cleanup function could be called in the end of the testing,
between the subtests, or in the middle of a test, each of them
has different needs.
BUG=b:144925225
TEST=run bluetooth_AdapterLESanity.le_connect_disconnect_loop
run bluetooth_AdapterLESanity
run bluetooth_AdapterQSSanity.stress
Also run quick sanity with Fizz device.
Change-Id: If81c3158e55fc06b46c1facb418fa14f8a8880d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/1981656
Reviewed-by: Daniel Winkler <danielwinkler@google.com>
Tested-by: Yun-Hao Chung <howardchung@google.com>
Commit-Queue: Yun-Hao Chung <howardchung@google.com>
diff --git a/client/cros/bluetooth/bluetooth_device_xmlrpc_server.py b/client/cros/bluetooth/bluetooth_device_xmlrpc_server.py
index 3270abf..b30bc48 100755
--- a/client/cros/bluetooth/bluetooth_device_xmlrpc_server.py
+++ b/client/cros/bluetooth/bluetooth_device_xmlrpc_server.py
@@ -116,6 +116,7 @@
BLUETOOTH_LIBDIR = '/var/lib/bluetooth'
BTMON_STOP_DELAY_SECS = 3
+ BTMON_LOG_PATH = '/var/log/btsnoop.log'
# Timeout for how long we'll wait for BlueZ and the Adapter to show up
# after reset.
@@ -168,7 +169,8 @@
# Initailize a btmon object to record bluetoothd's activity.
self.btmon = output_recorder.OutputRecorder(
- 'btmon', stop_delay_secs=self.BTMON_STOP_DELAY_SECS)
+ ('btmon -SAw %s' % self.BTMON_LOG_PATH).split(' '),
+ stop_delay_secs=self.BTMON_STOP_DELAY_SECS)
self.advertisements = []
self._adv_mainloop = gobject.MainLoop()
diff --git a/client/cros/bluetooth/output_recorder.py b/client/cros/bluetooth/output_recorder.py
index f13c6b0..adbe883 100644
--- a/client/cros/bluetooth/output_recorder.py
+++ b/client/cros/bluetooth/output_recorder.py
@@ -105,7 +105,8 @@
# special unicode such that we would like to escape.
# In this way, regular expression search could be conducted
# properly.
- self.contents.append(line.encode('unicode-escape'))
+ line = line.decode(errors='ignore').encode('unicode-escape')
+ self.contents.append(line)
elif self._stop_recording_thread_event.is_set():
self._stop_recording_thread_event.clear()
break
diff --git a/client/cros/chameleon/chameleon.py b/client/cros/chameleon/chameleon.py
index 4f14c8c..0921e04 100644
--- a/client/cros/chameleon/chameleon.py
+++ b/client/cros/chameleon/chameleon.py
@@ -27,6 +27,7 @@
CHAMELEON_PORT = 9992
CHAMELEOND_LOG_REMOTE_PATH = '/var/log/chameleond'
DAEMON_LOG_REMOTE_PATH = '/var/log/daemon.log'
+BTMON_LOG_REMOTE_PATH = '/var/log/btsnoop.log'
CHAMELEON_READY_TEST = 'GetSupportedPorts'
@@ -320,6 +321,42 @@
atexit.register(log_new_func)
+ def btmon_atexit_gen(btmon_pid):
+ """Generate a function to kill the btmon process and save the log
+
+ @param btmon_pid: PID of the btmon process
+ """
+
+ def btmon_atexit():
+ """Kill the btmon with specified PID and save the log"""
+
+ file_name = os.path.basename(BTMON_LOG_REMOTE_PATH)
+ target_path = os.path.join(log_dir, file_name)
+
+ self.host.run('kill %d' % btmon_pid)
+ self.host.get_file(BTMON_LOG_REMOTE_PATH, target_path)
+ return btmon_atexit
+
+
+ # Kill all btmon process before creating a new one
+ self.host.run('pkill btmon || true')
+
+ # Get available btmon options in the chameleon host
+ btmon_options = ''
+ btmon_help = self.host.run('btmon --help').stdout
+
+ for option in 'SA':
+ if '-%s' % option in btmon_help:
+ btmon_options += option
+
+ # Store btmon log
+ btmon_pid = int(self.host.run_background('btmon -%sw %s'
+ % (btmon_options,
+ BTMON_LOG_REMOTE_PATH)))
+ if btmon_pid > 0:
+ atexit.register(btmon_atexit_gen(btmon_pid))
+
+
def reboot(self):
"""Reboots Chameleon board."""
self._chameleond_proxy.Reboot()
diff --git a/server/cros/bluetooth/bluetooth_adapter_quick_tests.py b/server/cros/bluetooth/bluetooth_adapter_quick_tests.py
index e980ba0..885e75c 100644
--- a/server/cros/bluetooth/bluetooth_adapter_quick_tests.py
+++ b/server/cros/bluetooth/bluetooth_adapter_quick_tests.py
@@ -56,7 +56,7 @@
# Grab currect device list for initialization
connected_devices = self.devices
- self.cleanup(on_start=False)
+ self.cleanup(test_state='MID')
for device_type, device_list in connected_devices.items():
for device in device_list:
@@ -113,6 +113,10 @@
self.enable_disable_debug_log(enable=True)
+ # Kill all btmon process before creating a new one
+ self.bluetooth_facade.host.run('pkill btmon || true')
+ self.bluetooth_facade.btmon_start()
+
self.flag = flag
self.test_iter = None
@@ -273,7 +277,7 @@
self.group_chameleons_type()
# Close the connection between peers
- self.cleanup()
+ self.cleanup(test_state='NEW')
@staticmethod
diff --git a/server/cros/bluetooth/bluetooth_adapter_tests.py b/server/cros/bluetooth/bluetooth_adapter_tests.py
index 46d8af7..1e91f29 100644
--- a/server/cros/bluetooth/bluetooth_adapter_tests.py
+++ b/server/cros/bluetooth/bluetooth_adapter_tests.py
@@ -2877,10 +2877,19 @@
raise NotImplementedError
- def cleanup(self, on_start=True):
- """Clean up bluetooth adapter tests."""
- # Disable all the bluetooth debug logs
- self.enable_disable_debug_log(enable=False)
+ def cleanup(self, test_state='END'):
+ """Clean up bluetooth adapter tests.
+
+ @param test_state: string describing the requested clear is for
+ a new test(NEW), the middle of the test(MID),
+ or the end of the test(END).
+ """
+
+ if test_state is 'END':
+ # Disable all the bluetooth debug logs
+ self.enable_disable_debug_log(enable=False)
+ # Stop btmon process
+ self.bluetooth_facade.btmon_stop()
# Close the device properly if a device is instantiated.
# Note: do not write something like the following statements
@@ -2895,7 +2904,7 @@
device.Close()
# Power cycle BT device if we're in the middle of a test
- if not on_start:
+ if test_state is 'MID':
device.PowerCycle()
self.devices = dict()