1#!/usr/bin/env python3 2# 3# Copyright 2021 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import importlib 18import traceback 19import os 20import logging 21 22from functools import wraps 23from grpc import RpcError 24 25from acts import signals 26from acts.base_test import BaseTestClass 27from acts.context import get_current_context 28from acts.controllers.adb_lib.error import AdbCommandError 29 30from cert.ble_lib import enable_bluetooth, disable_bluetooth 31from cert.gd_device import MOBLY_CONTROLLER_CONFIG_NAME as CONTROLLER_CONFIG_NAME 32from cert.ble_lib import BleLib 33from facade import rootservice_pb2 as facade_rootservice 34 35 36class GdSl4aBaseTestClass(BaseTestClass): 37 38 SUBPROCESS_WAIT_TIMEOUT_SECONDS = 10 39 40 def setup_class(self, cert_module): 41 self.log_path_base = get_current_context().get_full_output_path() 42 self.verbose_mode = bool(self.user_params.get('verbose_mode', False)) 43 for config in self.controller_configs[CONTROLLER_CONFIG_NAME]: 44 config['verbose_mode'] = self.verbose_mode 45 self.cert_module = cert_module 46 47 # Parse and construct GD device objects 48 self.register_controller(importlib.import_module('cert.gd_device'), builtin=True) 49 self.dut = self.android_devices[0] 50 self.cert = self.gd_devices[0] 51 52 # Enable full btsnoop log 53 self.dut.adb.shell("setprop persist.bluetooth.btsnooplogmode full") 54 getprop_result = self.dut.adb.shell("getprop persist.bluetooth.btsnooplogmode") == "full" 55 if not getprop_result: 56 self.dut.log.warning("Failed to enable Bluetooth Hci Snoop Logging.") 57 58 self.ble = BleLib(log=self.log, dut=self.dut) 59 60 def teardown_class(self): 61 pass 62 63 def setup_test(self): 64 self.cert.rootservice.StartStack( 65 facade_rootservice.StartStackRequest( 66 module_under_test=facade_rootservice.BluetoothModule.Value(self.cert_module),)) 67 self.cert.wait_channel_ready() 68 69 self.timer_list = [] 70 self.dut.ed.clear_all_events() 71 self.dut.droid.setScreenTimeout(500) 72 self.dut.droid.wakeUpNow() 73 74 # Always start tests with Bluetooth enabled and BLE disabled. 75 self.dut.droid.bluetoothDisableBLE() 76 disable_bluetooth(self.dut.droid, self.dut.ed) 77 # Enable full verbose logging for Bluetooth 78 self.dut.adb.shell("device_config put bluetooth INIT_logging_debug_enabled_for_all true") 79 # Then enable Bluetooth 80 enable_bluetooth(self.dut.droid, self.dut.ed) 81 self.dut.droid.bluetoothDisableBLE() 82 return True 83 84 def teardown_test(self): 85 # Make sure BLE is disabled and Bluetooth is disabled after test 86 self.dut.droid.bluetoothDisableBLE() 87 disable_bluetooth(self.dut.droid, self.dut.ed) 88 self.cert.rootservice.StopStack(facade_rootservice.StopStackRequest()) 89 90 # TODO: split cert logcat logs into individual tests 91 current_test_dir = get_current_context().get_full_output_path() 92 93 # Pull DUT logs 94 self.pull_dut_logs(current_test_dir) 95 96 # Pull CERT logs 97 self.cert.pull_logs(current_test_dir) 98 99 def pull_dut_logs(self, base_dir): 100 try: 101 self.dut.pull_files("/data/misc/bluetooth/logs/btsnoop_hci.log", 102 os.path.join(base_dir, "DUT_%s_btsnoop_hci.log" % self.dut.serial)) 103 self.dut.pull_files("/data/misc/bluedroid/bt_config.conf", 104 os.path.join(base_dir, "DUT_%s_bt_config.conf" % self.dut.serial)) 105 self.dut.pull_files("/data/misc/bluedroid/bt_config.bak", 106 os.path.join(base_dir, "DUT_%s_bt_config.bak" % self.dut.serial)) 107 except AdbCommandError as error: 108 logging.warning("Failed to pull logs from DUT: " + str(error)) 109 110 def __getattribute__(self, name): 111 attr = super().__getattribute__(name) 112 if not callable(attr) or not GdSl4aBaseTestClass.__is_entry_function(name): 113 return attr 114 115 @wraps(attr) 116 def __wrapped(*args, **kwargs): 117 try: 118 return attr(*args, **kwargs) 119 except RpcError as e: 120 exception_info = "".join(traceback.format_exception(e.__class__, e, e.__traceback__)) 121 raise signals.TestFailure("RpcError during test\n\nRpcError:\n\n%s" % (exception_info)) 122 123 return __wrapped 124 125 __ENTRY_METHODS = {"setup_class", "teardown_class", "setup_test", "teardown_test"} 126 127 @staticmethod 128 def __is_entry_function(name): 129 return name.startswith("test_") or name in GdSl4aBaseTestClass.__ENTRY_METHODS 130