Loading system/gd/Android.mk +6 −0 Original line number Original line 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 += \ bluetooth_cert_test_file_list += \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_SHARED_LIBRARIES)/bluetooth_packets_python3.so \ $(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)/libbluetooth_gd.so \ $(HOST_OUT_SHARED_LIBRARIES)/libc++.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)/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_EXECUTABLES)/bluetooth_stack_with_facade \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ Loading system/gd/cert/cert_self_test.py +9 −1 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,7 @@ import time from mobly import asserts from mobly import asserts from datetime import datetime, timedelta from datetime import datetime, timedelta from acts.base_test import BaseTestClass from acts.base_test import BaseTestClass from cert.event_stream import EventStream from cert.event_stream import EventStream, FilteringEventStream from cert.truth import assertThat from cert.truth import assertThat # Test packet nesting # Test packet nesting Loading Loading @@ -386,3 +386,11 @@ class CertSelfTest(BaseTestClass): logging.debug(e) logging.debug(e) return True # Failed as expected return True # Failed as expected return False 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 Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ class IEventStream(ABC): class FilteringEventStream(IEventStream): class FilteringEventStream(IEventStream): def __init__(self, stream, filter_fn): 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.event_queue = SimpleQueue() self.stream = stream self.stream = stream Loading Loading @@ -264,11 +264,12 @@ def NOT_FOR_YOU_assert_event_occurs( try: try: current_event = istream.get_event_queue().get( current_event = istream.get_event_queue().get( timeout=remaining.total_seconds()) timeout=remaining.total_seconds()) logging.debug("current_event: %s", current_event) if match_fn(current_event): if match_fn(current_event): event_list.append(current_event) event_list.append(current_event) except Empty: except Empty: continue continue logging.debug("Done waiting for event") logging.debug("Done waiting for event, received %d", len(event_list)) asserts.assert_true( asserts.assert_true( len(event_list) >= at_least_times, len(event_list) >= at_least_times, msg=("Expected at least %d events, but got %d" % (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 Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # See the License for the specific language governing permissions and # limitations under the License. # limitations under the License. from acts import asserts from acts.base_test import BaseTestClass from acts.base_test import BaseTestClass from facade import rootservice_pb2 as facade_rootservice from facade import rootservice_pb2 as facade_rootservice Loading @@ -24,6 +25,14 @@ import signal import subprocess 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): class GdFacadeOnlyBaseTestClass(BaseTestClass): def setup_class(self, dut_module, cert_module): def setup_class(self, dut_module, cert_module): Loading Loading @@ -54,9 +63,14 @@ class GdFacadeOnlyBaseTestClass(BaseTestClass): env=os.environ.copy(), env=os.environ.copy(), stdout=self.rootcanal_logs, stdout=self.rootcanal_logs, stderr=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: for gd_device in gd_devices: gd_device["rootcanal_port"] = rootcanal_hci_port gd_device["rootcanal_port"] = rootcanal_hci_port self.register_controller( self.register_controller( importlib.import_module('cert.gd_device'), builtin=True) importlib.import_module('cert.gd_device'), builtin=True) Loading system/gd/cert/gd_device_base.py +124 −15 Original line number Original line Diff line number Diff line Loading @@ -23,18 +23,21 @@ import socket import subprocess import subprocess import time import time from acts import asserts from acts import context from acts import context from acts.controllers.adb import AdbProxy from acts.controllers.adb import AdbProxy, AdbError import grpc import grpc from cert.environment_provider import PRODUCT_DEVICE from cert.environment_provider import PRODUCT_DEVICE from cert.gd_base_test_facade_only import is_subprocess_alive ANDROID_PRODUCT_OUT = os.path.join( ANDROID_PRODUCT_OUT = os.path.join( os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", PRODUCT_DEVICE) PRODUCT_DEVICE) WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_FOR_DEVICE_TIMEOUT = 180 def replace_vars(string, config): def replace_vars(string, config): Loading Loading @@ -77,26 +80,31 @@ class GdDeviceBase: self.serial_number = serial_number self.serial_number = serial_number if self.serial_number: if self.serial_number: self.ad = AdbProxy(serial_number) self.adb = AdbProxy(self.serial_number) self.ad.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.ensure_verity_disabled() self.ad.tcp_forward(int(grpc_port), int(grpc_port)) asserts.assert_true( self.ad.tcp_forward( 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)) int(grpc_root_server_port), int(grpc_root_server_port)) self.ad.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.adb.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/bin/bluetooth_stack_with_facade"), "system/bin/bluetooth_stack_with_facade"), "system/bin") "system/bin") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libbluetooth_gd.so"), "system/lib64") "system/lib64/libbluetooth_gd.so"), "system/lib64") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libgrpc++_unsecure.so"), "system/lib64/libgrpc++_unsecure.so"), "system/lib64") "system/lib64") self.ad.shell("logcat -c") self.ensure_no_output(self.adb.shell("logcat -c")) self.ad.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ad.shell("svc bluetooth disable") self.ensure_no_output(self.adb.shell("svc bluetooth disable")) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, Loading @@ -111,6 +119,13 @@ class GdDeviceBase: env=os.environ.copy(), env=os.environ.copy(), stdout=self.backing_process_logs, stdout=self.backing_process_logs, stderr=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.accept() tester_signal_socket.close() tester_signal_socket.close() Loading @@ -131,11 +146,11 @@ class GdDeviceBase: (self.label, backing_process_return_code)) (self.label, backing_process_return_code)) if self.serial_number: if self.serial_number: self.ad.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.adb.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.ad.pull( self.adb.pull( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( self.log_path_base, "%s_btsnoop_hci.log" % self.label)) 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( "/data/misc/bluetooth/logs/system_log %s" % os.path.join( self.log_path_base, "%s_system_log" % self.label)) self.log_path_base, "%s_system_log" % self.label)) Loading @@ -145,3 +160,97 @@ class GdDeviceBase: future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) except grpc.FutureTimeoutError: except grpc.FutureTimeoutError: logging.error("wait channel ready timeout") 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 Original line 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 += \ bluetooth_cert_test_file_list += \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_EXECUTABLES)/bluetooth_stack_with_facade \ $(HOST_OUT_SHARED_LIBRARIES)/bluetooth_packets_python3.so \ $(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)/libbluetooth_gd.so \ $(HOST_OUT_SHARED_LIBRARIES)/libc++.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)/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_EXECUTABLES)/bluetooth_stack_with_facade \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libbluetooth_gd.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ $(TARGET_OUT_SHARED_LIBRARIES)/libgrpc++_unsecure.so \ Loading
system/gd/cert/cert_self_test.py +9 −1 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,7 @@ import time from mobly import asserts from mobly import asserts from datetime import datetime, timedelta from datetime import datetime, timedelta from acts.base_test import BaseTestClass from acts.base_test import BaseTestClass from cert.event_stream import EventStream from cert.event_stream import EventStream, FilteringEventStream from cert.truth import assertThat from cert.truth import assertThat # Test packet nesting # Test packet nesting Loading Loading @@ -386,3 +386,11 @@ class CertSelfTest(BaseTestClass): logging.debug(e) logging.debug(e) return True # Failed as expected return True # Failed as expected return False 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 Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ class IEventStream(ABC): class FilteringEventStream(IEventStream): class FilteringEventStream(IEventStream): def __init__(self, stream, filter_fn): 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.event_queue = SimpleQueue() self.stream = stream self.stream = stream Loading Loading @@ -264,11 +264,12 @@ def NOT_FOR_YOU_assert_event_occurs( try: try: current_event = istream.get_event_queue().get( current_event = istream.get_event_queue().get( timeout=remaining.total_seconds()) timeout=remaining.total_seconds()) logging.debug("current_event: %s", current_event) if match_fn(current_event): if match_fn(current_event): event_list.append(current_event) event_list.append(current_event) except Empty: except Empty: continue continue logging.debug("Done waiting for event") logging.debug("Done waiting for event, received %d", len(event_list)) asserts.assert_true( asserts.assert_true( len(event_list) >= at_least_times, len(event_list) >= at_least_times, msg=("Expected at least %d events, but got %d" % (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 Original line Diff line number Diff line Loading @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # See the License for the specific language governing permissions and # limitations under the License. # limitations under the License. from acts import asserts from acts.base_test import BaseTestClass from acts.base_test import BaseTestClass from facade import rootservice_pb2 as facade_rootservice from facade import rootservice_pb2 as facade_rootservice Loading @@ -24,6 +25,14 @@ import signal import subprocess 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): class GdFacadeOnlyBaseTestClass(BaseTestClass): def setup_class(self, dut_module, cert_module): def setup_class(self, dut_module, cert_module): Loading Loading @@ -54,9 +63,14 @@ class GdFacadeOnlyBaseTestClass(BaseTestClass): env=os.environ.copy(), env=os.environ.copy(), stdout=self.rootcanal_logs, stdout=self.rootcanal_logs, stderr=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: for gd_device in gd_devices: gd_device["rootcanal_port"] = rootcanal_hci_port gd_device["rootcanal_port"] = rootcanal_hci_port self.register_controller( self.register_controller( importlib.import_module('cert.gd_device'), builtin=True) importlib.import_module('cert.gd_device'), builtin=True) Loading
system/gd/cert/gd_device_base.py +124 −15 Original line number Original line Diff line number Diff line Loading @@ -23,18 +23,21 @@ import socket import subprocess import subprocess import time import time from acts import asserts from acts import context from acts import context from acts.controllers.adb import AdbProxy from acts.controllers.adb import AdbProxy, AdbError import grpc import grpc from cert.environment_provider import PRODUCT_DEVICE from cert.environment_provider import PRODUCT_DEVICE from cert.gd_base_test_facade_only import is_subprocess_alive ANDROID_PRODUCT_OUT = os.path.join( ANDROID_PRODUCT_OUT = os.path.join( os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", os.getcwd(), "out/dist/bluetooth_cert_test/out/target/product", PRODUCT_DEVICE) PRODUCT_DEVICE) WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_CHANNEL_READY_TIMEOUT = 10 WAIT_FOR_DEVICE_TIMEOUT = 180 def replace_vars(string, config): def replace_vars(string, config): Loading Loading @@ -77,26 +80,31 @@ class GdDeviceBase: self.serial_number = serial_number self.serial_number = serial_number if self.serial_number: if self.serial_number: self.ad = AdbProxy(serial_number) self.adb = AdbProxy(self.serial_number) self.ad.shell("date " + time.strftime("%m%d%H%M%Y.%S")) self.ensure_verity_disabled() self.ad.tcp_forward(int(grpc_port), int(grpc_port)) asserts.assert_true( self.ad.tcp_forward( 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)) int(grpc_root_server_port), int(grpc_root_server_port)) self.ad.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.adb.reverse("tcp:%s tcp:%s" % (signal_port, signal_port)) self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/bin/bluetooth_stack_with_facade"), "system/bin/bluetooth_stack_with_facade"), "system/bin") "system/bin") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libbluetooth_gd.so"), "system/lib64") "system/lib64/libbluetooth_gd.so"), "system/lib64") self.ad.push( self.push_or_die( os.path.join(ANDROID_PRODUCT_OUT, os.path.join(ANDROID_PRODUCT_OUT, "system/lib64/libgrpc++_unsecure.so"), "system/lib64/libgrpc++_unsecure.so"), "system/lib64") "system/lib64") self.ad.shell("logcat -c") self.ensure_no_output(self.adb.shell("logcat -c")) self.ad.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.adb.shell("rm /data/misc/bluetooth/logs/btsnoop_hci.log") self.ad.shell("svc bluetooth disable") self.ensure_no_output(self.adb.shell("svc bluetooth disable")) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, tester_signal_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, Loading @@ -111,6 +119,13 @@ class GdDeviceBase: env=os.environ.copy(), env=os.environ.copy(), stdout=self.backing_process_logs, stdout=self.backing_process_logs, stderr=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.accept() tester_signal_socket.close() tester_signal_socket.close() Loading @@ -131,11 +146,11 @@ class GdDeviceBase: (self.label, backing_process_return_code)) (self.label, backing_process_return_code)) if self.serial_number: if self.serial_number: self.ad.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.adb.shell("logcat -d -f /data/misc/bluetooth/logs/system_log") self.ad.pull( self.adb.pull( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( "/data/misc/bluetooth/logs/btsnoop_hci.log %s" % os.path.join( self.log_path_base, "%s_btsnoop_hci.log" % self.label)) 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( "/data/misc/bluetooth/logs/system_log %s" % os.path.join( self.log_path_base, "%s_system_log" % self.label)) self.log_path_base, "%s_system_log" % self.label)) Loading @@ -145,3 +160,97 @@ class GdDeviceBase: future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) future.result(timeout=WAIT_CHANNEL_READY_TIMEOUT) except grpc.FutureTimeoutError: except grpc.FutureTimeoutError: logging.error("wait channel ready timeout") 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)