Loading system/gd/Android.mk +6 −0 Original line number Diff line number Diff line Loading @@ -11,9 +11,15 @@ bluetooth_cert_test_file_list := $(addprefix $(LOCAL_PATH)/,$(bluetooth_cert_tes bluetooth_cert_test_file_list += \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_SHARED_LIBRARIES)/bluetooth_packets_python3.so \ $(HOST_OUT_SHARED_LIBRARIES)/libbase.so \ $(HOST_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(HOST_OUT_SHARED_LIBRARIES)/libc++.so \ $(HOST_OUT_SHARED_LIBRARIES)/libchrome.so \ $(HOST_OUT_SHARED_LIBRARIES)/libevent-host.so \ $(HOST_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ $(HOST_OUT_SHARED_LIBRARIES)/liblog.so \ $(HOST_OUT_SHARED_LIBRARIES)/libz-host.so \ $(HOST_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-full.so \ $(TARGET_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ Loading system/gd/cert/cert_self_test.py +9 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import time from mobly import asserts from datetime import datetime, timedelta from acts.base_test import BaseTestClass from cert.event_stream import EventStream from cert.event_stream import EventStream, FilteringEventStream from cert.truth import assertThat # Test packet nesting Loading Loading @@ -386,3 +386,11 @@ class CertSelfTest(BaseTestClass): logging.debug(e) return True # Failed as expected return False def test_filtering_event_stream_none_filter_function(self): with EventStream(FetchEvents(events=[1, 2, 3], delay_ms=50)) as event_stream: filtered_event_stream = FilteringEventStream(event_stream, None) assertThat(filtered_event_stream)\ .emits(lambda data: data.value_ == 1)\ .then(lambda data: data.value_ == 3) system/gd/cert/event_stream.py +3 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ class IEventStream(ABC): class FilteringEventStream(IEventStream): def __init__(self, stream, filter_fn): self.filter_fn = filter_fn self.filter_fn = filter_fn if filter_fn else lambda x: x self.event_queue = SimpleQueue() self.stream = stream Loading Loading @@ -264,11 +264,12 @@ def NOT_FOR_YOU_assert_event_occurs( try: current_event = istream.get_event_queue().get( timeout=remaining.total_seconds()) logging.debug("current_event: %s", current_event) if match_fn(current_event): event_list.append(current_event) except Empty: continue logging.debug("Done waiting for event") logging.debug("Done waiting for event, received %d", len(event_list)) asserts.assert_true( len(event_list) >= at_least_times, msg=("Expected at least %d events, but got %d" % (at_least_times, Loading system/gd/cert/gd_base_test_facade_only.py +15 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from acts import asserts from acts.base_test import BaseTestClass from facade import rootservice_pb2 as facade_rootservice Loading @@ -24,6 +25,14 @@ import signal import subprocess def is_subprocess_alive(process, timeout_seconds=1): try: process.wait(timeout=timeout_seconds) return False except subprocess.TimeoutExpired as exp: return True class GdFacadeOnlyBaseTestClass(BaseTestClass): def setup_class(self, dut_module, cert_module): Loading Loading @@ -54,9 +63,14 @@ class GdFacadeOnlyBaseTestClass(BaseTestClass): env=os.environ.copy(), stdout=self.rootcanal_logs, stderr=self.rootcanal_logs) asserts.assert_true( self.rootcanal_process, msg="Cannot start root-canal at " + str(rootcanal)) asserts.assert_true( is_subprocess_alive(self.rootcanal_process), msg="root-canal stopped immediately after running") for gd_device in gd_devices: gd_device["rootcanal_port"] = rootcanal_hci_port self.register_controller( importlib.import_module('cert.gd_device'), builtin=True) Loading system/gd/cert/gd_device_base.py +124 −15 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ import socket import subprocess import time from acts import asserts from acts import context from acts.controllers.adb import AdbProxy from acts.controllers.adb import AdbProxy, AdbError import grpc from cert.environment_provider import PRODUCT_DEVICE from cert.gd_base_test_facade_only import is_subprocess_alive ANDROID_PRODUCT_OUT = os.path.join( os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", PRODUCT_DEVICE) WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_FOR_DEVICE_TIMEOUT = 180 def replace_vars(string, config): Loading Loading @@ -77,26 +80,31 @@ class GdDeviceBase: self.serial_number = serial_number if self.serial_number: self.ad = AdbProxy(serial_number) self.ad.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.ad.tcp_forward(int(grpc_port), int(grpc_port)) self.ad.tcp_forward( self.adb = AdbProxy(self.serial_number) self.ensure_verity_disabled() asserts.assert_true( self.adb.ensure_root(), msg="device %s cannot run as root after enabling verity" % self.serial_number) self.adb.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.adb.tcp_forward(int(grpc_port), int(grpc_port)) self.adb.tcp_forward( int(grpc_root_server_port), int(grpc_root_server_port)) self.ad.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.ad.push( self.adb.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/bin/bluetooth_stack_with_facade"), "system/bin") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libbluetooth_gd.so"), "system/lib64") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libgrpc++_unsecure.so"), "system/lib64") self.ad.shell("logcat -c") self.ad.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ad.shell("svc bluetooth disable") self.ensure_no_output(self.adb.shell("logcat -c")) self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ensure_no_output(self.adb.shell("svc bluetooth disable")) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, Loading @@ -111,6 +119,13 @@ class GdDeviceBase: env=os.environ.copy(), stdout=self.backing_process_logs, stderr=self.backing_process_logs) asserts.assert_true( self.backing_process, msg="Cannot start backing_process at " + " ".join(cmd)) asserts.assert_true( is_subprocess_alive(self.backing_process), msg="backing_process stopped immediately after running " + " ".join(cmd)) tester_signal_socket.accept() tester_signal_socket.close() Loading @@ -131,11 +146,11 @@ class GdDeviceBase: (self.label, backing_process_return_code)) if self.serial_number: self.ad.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.ad.pull( self.adb.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.adb.pull( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( self.log_path_base, "%s_btsnoop_hci.log" % self.label)) self.ad.pull( self.adb.pull( "/data/misc/bluetooth/logs/system_log %s" % os.path.join( self.log_path_base, "%s_system_log" % self.label)) Loading @@ -145,3 +160,97 @@ class GdDeviceBase: future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) except grpc.FutureTimeoutError: logging.error("wait channel ready timeout") def ensure_no_output(self, result): """ Ensure a command has not output """ asserts.assert_true( result is None or len(result) == 0, msg="command returned something when it shouldn't: %s" % result) def push_or_die(self, src_file_path, dst_file_path, push_timeout=300): """Pushes a file to the Android device Args: src_file_path: The path to the file to install. dst_file_path: The destination of the file. push_timeout: How long to wait for the push to finish in seconds """ try: self.adb.ensure_root() self.ensure_verity_disabled() out = self.adb.push( '%s %s' % (src_file_path, dst_file_path), timeout=push_timeout) if 'error' in out: asserts.fail('Unable to push file %s to %s due to %s' % (src_file_path, dst_file_path, out)) except Exception as e: asserts.fail( msg='Unable to push file %s to %s due to %s' % (src_file_path, dst_file_path, e), extras=e) def ensure_verity_disabled(self): """Ensures that verity is enabled. If verity is not enabled, this call will reboot the phone. Note that this only works on debuggable builds. """ logging.debug("Disabling verity and remount for %s", self.serial_number) asserts.assert_true(self.adb.ensure_root(), "device %s cannot run as root", self.serial_number) # The below properties will only exist if verity has been enabled. system_verity = self.adb.getprop('partition.system.verified') vendor_verity = self.adb.getprop('partition.vendor.verified') if system_verity or vendor_verity: self.adb.disable_verity() self.reboot() self.adb.remount() self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT) def reboot(self, timeout_minutes=15.0): """Reboots the device. Reboot the device, wait for device to complete booting. """ logging.debug("Rebooting %s", self.serial_number) self.adb.reboot() timeout_start = time.time() timeout = timeout_minutes * 60 # Android sometimes return early after `adb reboot` is called. This # means subsequent calls may make it to the device before the reboot # goes through, return false positives for getprops such as # sys.boot_completed. while time.time() < timeout_start + timeout: try: self.adb.get_state() time.sleep(.1) except AdbError: # get_state will raise an error if the device is not found. We # want the device to be missing to prove the device has kicked # off the reboot. break minutes_left = timeout_minutes - (time.time() - timeout_start) / 60.0 self.wait_for_boot_completion(timeout_minutes=minutes_left) def wait_for_boot_completion(self, timeout_minutes=15.0): """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED. """ timeout_start = time.time() timeout = timeout_minutes * 60 self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT) while time.time() < timeout_start + timeout: try: completed = self.adb.getprop("sys.boot_completed") if completed == '1': return except AdbError: # adb shell calls may fail during certain period of booting # process, which is normal. Ignoring these errors. pass time.sleep(5) asserts.fail(msg='Device %s booting process timed out.' % self.serial_number) Loading
system/gd/Android.mk +6 −0 Original line number Diff line number Diff line Loading @@ -11,9 +11,15 @@ bluetooth_cert_test_file_list := $(addprefix $(LOCAL_PATH)/,$(bluetooth_cert_tes bluetooth_cert_test_file_list += \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_SHARED_LIBRARIES)/bluetooth_packets_python3.so \ $(HOST_OUT_SHARED_LIBRARIES)/libbase.so \ $(HOST_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(HOST_OUT_SHARED_LIBRARIES)/libc++.so \ $(HOST_OUT_SHARED_LIBRARIES)/libchrome.so \ $(HOST_OUT_SHARED_LIBRARIES)/libevent-host.so \ $(HOST_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ $(HOST_OUT_SHARED_LIBRARIES)/liblog.so \ $(HOST_OUT_SHARED_LIBRARIES)/libz-host.so \ $(HOST_OUT_SHARED_LIBRARIES)/libprotobuf-cpp-full.so \ $(TARGET_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ Loading
system/gd/cert/cert_self_test.py +9 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ import time from mobly import asserts from datetime import datetime, timedelta from acts.base_test import BaseTestClass from cert.event_stream import EventStream from cert.event_stream import EventStream, FilteringEventStream from cert.truth import assertThat # Test packet nesting Loading Loading @@ -386,3 +386,11 @@ class CertSelfTest(BaseTestClass): logging.debug(e) return True # Failed as expected return False def test_filtering_event_stream_none_filter_function(self): with EventStream(FetchEvents(events=[1, 2, 3], delay_ms=50)) as event_stream: filtered_event_stream = FilteringEventStream(event_stream, None) assertThat(filtered_event_stream)\ .emits(lambda data: data.value_ == 1)\ .then(lambda data: data.value_ == 3)
system/gd/cert/event_stream.py +3 −2 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ class IEventStream(ABC): class FilteringEventStream(IEventStream): def __init__(self, stream, filter_fn): self.filter_fn = filter_fn self.filter_fn = filter_fn if filter_fn else lambda x: x self.event_queue = SimpleQueue() self.stream = stream Loading Loading @@ -264,11 +264,12 @@ def NOT_FOR_YOU_assert_event_occurs( try: current_event = istream.get_event_queue().get( timeout=remaining.total_seconds()) logging.debug("current_event: %s", current_event) if match_fn(current_event): event_list.append(current_event) except Empty: continue logging.debug("Done waiting for event") logging.debug("Done waiting for event, received %d", len(event_list)) asserts.assert_true( len(event_list) >= at_least_times, msg=("Expected at least %d events, but got %d" % (at_least_times, Loading
system/gd/cert/gd_base_test_facade_only.py +15 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from acts import asserts from acts.base_test import BaseTestClass from facade import rootservice_pb2 as facade_rootservice Loading @@ -24,6 +25,14 @@ import signal import subprocess def is_subprocess_alive(process, timeout_seconds=1): try: process.wait(timeout=timeout_seconds) return False except subprocess.TimeoutExpired as exp: return True class GdFacadeOnlyBaseTestClass(BaseTestClass): def setup_class(self, dut_module, cert_module): Loading Loading @@ -54,9 +63,14 @@ class GdFacadeOnlyBaseTestClass(BaseTestClass): env=os.environ.copy(), stdout=self.rootcanal_logs, stderr=self.rootcanal_logs) asserts.assert_true( self.rootcanal_process, msg="Cannot start root-canal at " + str(rootcanal)) asserts.assert_true( is_subprocess_alive(self.rootcanal_process), msg="root-canal stopped immediately after running") for gd_device in gd_devices: gd_device["rootcanal_port"] = rootcanal_hci_port self.register_controller( importlib.import_module('cert.gd_device'), builtin=True) Loading
system/gd/cert/gd_device_base.py +124 −15 Original line number Diff line number Diff line Loading @@ -23,18 +23,21 @@ import socket import subprocess import time from acts import asserts from acts import context from acts.controllers.adb import AdbProxy from acts.controllers.adb import AdbProxy, AdbError import grpc from cert.environment_provider import PRODUCT_DEVICE from cert.gd_base_test_facade_only import is_subprocess_alive ANDROID_PRODUCT_OUT = os.path.join( os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", PRODUCT_DEVICE) WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_FOR_DEVICE_TIMEOUT = 180 def replace_vars(string, config): Loading Loading @@ -77,26 +80,31 @@ class GdDeviceBase: self.serial_number = serial_number if self.serial_number: self.ad = AdbProxy(serial_number) self.ad.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.ad.tcp_forward(int(grpc_port), int(grpc_port)) self.ad.tcp_forward( self.adb = AdbProxy(self.serial_number) self.ensure_verity_disabled() asserts.assert_true( self.adb.ensure_root(), msg="device %s cannot run as root after enabling verity" % self.serial_number) self.adb.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.adb.tcp_forward(int(grpc_port), int(grpc_port)) self.adb.tcp_forward( int(grpc_root_server_port), int(grpc_root_server_port)) self.ad.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.ad.push( self.adb.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/bin/bluetooth_stack_with_facade"), "system/bin") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libbluetooth_gd.so"), "system/lib64") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libgrpc++_unsecure.so"), "system/lib64") self.ad.shell("logcat -c") self.ad.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ad.shell("svc bluetooth disable") self.ensure_no_output(self.adb.shell("logcat -c")) self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ensure_no_output(self.adb.shell("svc bluetooth disable")) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, Loading @@ -111,6 +119,13 @@ class GdDeviceBase: env=os.environ.copy(), stdout=self.backing_process_logs, stderr=self.backing_process_logs) asserts.assert_true( self.backing_process, msg="Cannot start backing_process at " + " ".join(cmd)) asserts.assert_true( is_subprocess_alive(self.backing_process), msg="backing_process stopped immediately after running " + " ".join(cmd)) tester_signal_socket.accept() tester_signal_socket.close() Loading @@ -131,11 +146,11 @@ class GdDeviceBase: (self.label, backing_process_return_code)) if self.serial_number: self.ad.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.ad.pull( self.adb.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.adb.pull( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( self.log_path_base, "%s_btsnoop_hci.log" % self.label)) self.ad.pull( self.adb.pull( "/data/misc/bluetooth/logs/system_log %s" % os.path.join( self.log_path_base, "%s_system_log" % self.label)) Loading @@ -145,3 +160,97 @@ class GdDeviceBase: future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) except grpc.FutureTimeoutError: logging.error("wait channel ready timeout") def ensure_no_output(self, result): """ Ensure a command has not output """ asserts.assert_true( result is None or len(result) == 0, msg="command returned something when it shouldn't: %s" % result) def push_or_die(self, src_file_path, dst_file_path, push_timeout=300): """Pushes a file to the Android device Args: src_file_path: The path to the file to install. dst_file_path: The destination of the file. push_timeout: How long to wait for the push to finish in seconds """ try: self.adb.ensure_root() self.ensure_verity_disabled() out = self.adb.push( '%s %s' % (src_file_path, dst_file_path), timeout=push_timeout) if 'error' in out: asserts.fail('Unable to push file %s to %s due to %s' % (src_file_path, dst_file_path, out)) except Exception as e: asserts.fail( msg='Unable to push file %s to %s due to %s' % (src_file_path, dst_file_path, e), extras=e) def ensure_verity_disabled(self): """Ensures that verity is enabled. If verity is not enabled, this call will reboot the phone. Note that this only works on debuggable builds. """ logging.debug("Disabling verity and remount for %s", self.serial_number) asserts.assert_true(self.adb.ensure_root(), "device %s cannot run as root", self.serial_number) # The below properties will only exist if verity has been enabled. system_verity = self.adb.getprop('partition.system.verified') vendor_verity = self.adb.getprop('partition.vendor.verified') if system_verity or vendor_verity: self.adb.disable_verity() self.reboot() self.adb.remount() self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT) def reboot(self, timeout_minutes=15.0): """Reboots the device. Reboot the device, wait for device to complete booting. """ logging.debug("Rebooting %s", self.serial_number) self.adb.reboot() timeout_start = time.time() timeout = timeout_minutes * 60 # Android sometimes return early after `adb reboot` is called. This # means subsequent calls may make it to the device before the reboot # goes through, return false positives for getprops such as # sys.boot_completed. while time.time() < timeout_start + timeout: try: self.adb.get_state() time.sleep(.1) except AdbError: # get_state will raise an error if the device is not found. We # want the device to be missing to prove the device has kicked # off the reboot. break minutes_left = timeout_minutes - (time.time() - timeout_start) / 60.0 self.wait_for_boot_completion(timeout_minutes=minutes_left) def wait_for_boot_completion(self, timeout_minutes=15.0): """Waits for Android framework to broadcast ACTION_BOOT_COMPLETED. """ timeout_start = time.time() timeout = timeout_minutes * 60 self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT) while time.time() < timeout_start + timeout: try: completed = self.adb.getprop("sys.boot_completed") if completed == '1': return except AdbError: # adb shell calls may fail during certain period of booting # process, which is normal. Ignoring these errors. pass time.sleep(5) asserts.fail(msg='Device %s booting process timed out.' % self.serial_number)