Loading android/pandora/mmi2grpc/mmi2grpc/gatt.py +15 −16 Original line number Diff line number Diff line Loading @@ -61,16 +61,18 @@ MMI_SERVER = { "GATT/SR/GAD/BV-01-C", } BASE_UUID = "0000XXXX-0000-1000-8000-00805F9B34FB" # These UUIDs are used as reference for GATT server tests BASE_READ_WRITE_SERVICE_UUID = "0000fffe-0000-1000-8000-00805f9b34fb" BASE_READ_CHARACTERISTIC_UUID = "0000ffd-0000-1000-8000-00805f9b34fb" BASE_WRITE_CHARACTERISTIC_UUID = "0000fffa-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_ENCRYPTED_CHARACTERISTIC_UUID = "0000fff9-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_ENCRYPTED_MITM_CHARACTERISTIC_UUID = "0000fff8-0000-1000-8000-00805f9b34fb" BASE_READ_DESCRIPTOR_UUID = "0000fff7-0000-1000-8000-00805f9b34fb" BASE_WRITE_DESCRIPTOR_UUID = "0000fff6-0000-1000-8000-00805f9b34fb" CUSTOM_SERVICE_UUID = "0000fff5-0000-1000-8000-00805f9b34fb" CUSTOM_CHARACTERISTIC_UUID = "0000fff4-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_SERVICE_UUID = "0000FFFE-0000-1000-8000-00805F9B34FB" BASE_READ_CHARACTERISTIC_UUID = "0000FFD-0000-1000-8000-00805F9B34FB" BASE_WRITE_CHARACTERISTIC_UUID = "0000FFFA-0000-1000-8000-00805F9B34FB" BASE_READ_WRITE_ENCRYPTED_CHARACTERISTIC_UUID = "0000FFF9-0000-1000-8000-00805F9B34FB" BASE_READ_WRITE_ENCRYPTED_MITM_CHARACTERISTIC_UUID = "0000FFF8-0000-1000-8000-00805F9B34FB" BASE_READ_DESCRIPTOR_UUID = "0000FFF7-0000-1000-8000-00805F9B34FB" BASE_WRITE_DESCRIPTOR_UUID = "0000FFF6-0000-1000-8000-00805F9B34FB" CUSTOM_SERVICE_UUID = "0000FFF5-0000-1000-8000-00805F9B34FB" CUSTOM_CHARACTERISTIC_UUID = "0000FFF4-0000-1000-8000-00805F9B34FB" class GATTProxy(ProfileProxy): Loading Loading @@ -1302,9 +1304,6 @@ class GATTProxy(ProfileProxy): return "OK" common_uuid = "0000XXXX-0000-1000-8000-00805f9b34fb" def stringHandleToInt(handle: str): return int(handle, 16) Loading @@ -1325,23 +1324,23 @@ def formatUuid(uuid: str): """ uuid_len = len(uuid) if uuid_len == 4: return common_uuid.replace(common_uuid[4:8], uuid.lower()) return BASE_UUID.replace(BASE_UUID[4:8], uuid.upper()) elif uuid_len == 32 or uuid_len == 39: uuidCharList = list(uuid.replace('-', '').lower()) uuidCharList = list(uuid.replace('-', '').upper()) uuidCharList.insert(20, '-') uuidCharList.insert(16, '-') uuidCharList.insert(12, '-') uuidCharList.insert(8, '-') return ''.join(uuidCharList) else: return uuid return uuid.upper() # PTS asks wrong uuid for services discovered by SDP in some tests def formatSdpUuid(uuid: str): if uuid[3] == '1': uuid = uuid[:3] + 'f' return common_uuid.replace(common_uuid[4:8], uuid.lower()) return BASE_UUID.replace(BASE_UUID[4:8], uuid.upper()) def compareIncludedServices(service, service_handle, included_handle, included_uuid): Loading android/pandora/server/src/com/android/pandora/Gatt.kt +5 −5 Original line number Diff line number Diff line Loading @@ -161,7 +161,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { .first() val uuidsList = arrayListOf<String>() for (parcelUuid in bluetoothDevice.getUuids()) { uuidsList.add(parcelUuid.toString()) uuidsList.add(parcelUuid.toString().uppercase()) } DiscoverServicesSdpResponse.newBuilder().addAllServiceUuids(uuidsList).build() } Loading Loading @@ -268,7 +268,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattService.newBuilder() .setHandle(fullService.instanceId) .setType(fullService.type) .setUuid(fullService.uuid.toString()) .setUuid(fullService.uuid.toString().uppercase()) .addAllIncludedServices(generateServicesList(service.includedServices, 1)) .addAllCharacteristics(generateCharacteristicsList(service.characteristics)) .build() Loading Loading @@ -379,7 +379,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattService.newBuilder() .setHandle(service.getInstanceId()) .setType(service.getType()) .setUuid(service.getUuid().toString()) .setUuid(service.getUuid().toString().uppercase()) .addAllIncludedServices(generateServicesList(service.getIncludedServices(), dpth + 1)) .addAllCharacteristics(generateCharacteristicsList(service.characteristics)) newServicesList.add(serviceBuilder.build()) Loading @@ -397,7 +397,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattCharacteristic.newBuilder() .setProperties(characteristic.getProperties()) .setPermissions(characteristic.getPermissions()) .setUuid(characteristic.getUuid().toString()) .setUuid(characteristic.getUuid().toString().uppercase()) .addAllDescriptors(generateDescriptorsList(characteristic.getDescriptors())) .setHandle(characteristic.getInstanceId()) newCharacteristicsList.add(characteristicBuilder.build()) Loading @@ -415,7 +415,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattCharacteristicDescriptor.newBuilder() .setHandle(descriptor.getInstanceId()) .setPermissions(descriptor.getPermissions()) .setUuid(descriptor.getUuid().toString()) .setUuid(descriptor.getUuid().toString().uppercase()) newDescriptorsList.add(descriptorBuilder.build()) } return newDescriptorsList Loading android/pandora/server/src/com/android/pandora/GattInstance.kt +1 −1 Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ class GattInstance(val mDevice: BluetoothDevice, val mTransport: Int, val mConte characteristic: BluetoothGattCharacteristic, value: ByteArray ) { Log.i(TAG, "onCharacteristicChanged, characteristic: " + characteristic.getUuid().toString()) Log.i(TAG, "onCharacteristicChanged, characteristic: " + characteristic.getUuid().toString().uppercase()) mCharacteristicChangedMap[characteristic] = true mOnCharacteristicChanged.value = true } Loading android/pandora/server/src/com/android/pandora/Host.kt +3 −3 Original line number Diff line number Diff line Loading @@ -648,7 +648,7 @@ class Host( for (serviceDataEntry in serviceData) { val parcelUuid = serviceDataEntry.key Log.d(TAG, parcelUuid.uuid.toString()) Log.d(TAG, parcelUuid.uuid.toString().uppercase()) // use upper case uuid as the key if (BluetoothUuid.is16BitUuid(parcelUuid)) { Loading @@ -673,7 +673,7 @@ class Host( } for (serviceUuid in scanRecord.serviceSolicitationUuids ?: listOf<ParcelUuid>()) { Log.d(TAG, serviceUuid.uuid.toString()) Log.d(TAG, serviceUuid.uuid.toString().uppercase()) if (BluetoothUuid.is16BitUuid(serviceUuid)) { val uuid16 = serviceUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addServiceSolicitationUuids16(uuid16) Loading @@ -687,7 +687,7 @@ class Host( } for (serviceUuid in scanRecord.serviceUuids ?: listOf<ParcelUuid>()) { Log.d(TAG, serviceUuid.uuid.toString()) Log.d(TAG, serviceUuid.uuid.toString().uppercase()) if (BluetoothUuid.is16BitUuid(serviceUuid)) { val uuid16 = serviceUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids16(uuid16) Loading android/pandora/test/asha_test.py +49 −63 Original line number Diff line number Diff line Loading @@ -20,19 +20,21 @@ import logging from avatar import BumblePandoraDevice, PandoraDevice, PandoraDevices, asynchronous, bumble_server from bumble.gatt import GATT_ASHA_SERVICE from bumble.smp import PairingDelegate from bumble.pairing import PairingDelegate from bumble_experimental.asha import AshaGattService, AshaService from mobly import base_test, signals, test_runner from mobly.asserts import assert_equal # type: ignore from mobly.asserts import assert_false # type: ignore from mobly.asserts import assert_in # type: ignore from mobly.asserts import skip # type: ignore from mobly.asserts import assert_is_not_none # type: ignore from mobly.asserts import assert_true # type: ignore from pandora._utils import AioStream from pandora.host_pb2 import PUBLIC, RANDOM, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse from pandora.security_pb2 import LE_LEVEL3 from pandora_experimental.asha_grpc_aio import Asha as AioAsha, add_AshaServicer_to_server from typing import List, Optional, Tuple ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str() ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str('-') HISYCNID: List[int] = [0x01, 0x02, 0x03, 0x04, 0x5, 0x6, 0x7, 0x8] COMPLETE_LOCAL_NAME: str = "Bumble" AUDIO_SIGNAL_AMPLITUDE = 0.8 Loading @@ -45,9 +47,6 @@ class Ear(enum.IntEnum): LEFT = 0 RIGHT = 1 def __repr__(self) -> str: return str(self.value) class ASHATest(base_test.BaseTestClass): # type: ignore[misc] devices: Optional[PandoraDevices] = None Loading @@ -60,18 +59,18 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] def setup_class(self) -> None: # Register experimental bumble servicers hook. bumble_server.register_servicer_hook( lambda bumble, server: add_AshaServicer_to_server(AshaService(bumble.device), server) lambda bumble, _, server: add_AshaServicer_to_server(AshaService(bumble.device), server) ) self.devices = PandoraDevices(self) self.dut, ref_left, ref_right, *_ = self.devices if isinstance(self.dut, BumblePandoraDevice): raise signals.TestAbortAll('DUT Bumble does not support Asha source') raise signals.TestAbortClass('DUT Bumble does not support Asha source') if not isinstance(ref_left, BumblePandoraDevice): raise signals.TestAbortAll('Test require Bumble as reference device(s)') raise signals.TestAbortClass('Test require Bumble as reference device(s)') if not isinstance(ref_right, BumblePandoraDevice): raise signals.TestAbortAll('Test require Bumble as reference device(s)') raise signals.TestAbortClass('Test require Bumble as reference device(s)') self.ref_left, self.ref_right = ref_left, ref_right Loading @@ -84,8 +83,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await asyncio.gather(self.dut.reset(), self.ref_left.reset(), self.ref_right.reset()) # ASHA hearing aid's IO capability is NO_OUTPUT_NO_INPUT setattr(self.ref_left.device, "io_capability", PairingDelegate.NO_OUTPUT_NO_INPUT) setattr(self.ref_right.device, "io_capability", PairingDelegate.NO_OUTPUT_NO_INPUT) self.ref_left.server_config.io_capability = PairingDelegate.NO_OUTPUT_NO_INPUT self.ref_right.server_config.io_capability = PairingDelegate.NO_OUTPUT_NO_INPUT async def ref_advertise_asha( self, ref_device: PandoraDevice, ref_address_type: OwnAddressType, ear: Ear Loading Loading @@ -125,7 +124,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) ) dut_scan.cancel() assert ref return ref async def dut_connect_to_ref( Loading @@ -141,9 +139,9 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_res.result_variant(), 'connection') dut_ref, ref_dut = dut_ref_res.connection, ref_dut_res.connection assert dut_ref and ref_dut assert_is_not_none(dut_ref) assert dut_ref advertisement.cancel() return dut_ref, ref_dut async def is_device_connected(self, device: PandoraDevice, connection: Connection, timeout: float) -> bool: Loading @@ -151,7 +149,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await device.aio.host.WaitDisconnection(connection=connection, timeout=timeout) return False except grpc.RpcError as e: assert e.code() == grpc.StatusCode.DEADLINE_EXCEEDED # type: ignore assert_equal(e.code(), grpc.StatusCode.DEADLINE_EXCEEDED) # type: ignore return True def get_expected_advertisement_data(self, ear: Ear) -> str: Loading Loading @@ -246,7 +244,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut # DUT starts pairing with the Ref. (secure, wait_security) = await asyncio.gather( Loading Loading @@ -280,7 +277,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=ear) # DUT initiates connection to ref_device. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() return dut_ref, ref_dut Loading Loading @@ -356,7 +352,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] logging.debug("result should come out") advertisement.cancel() assert dut_ref assert_is_not_none(dut_ref) secure = await self.dut.aio.security.Secure(connection=dut_ref, le=LE_LEVEL3) Loading @@ -378,8 +374,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut _, _ = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -401,11 +396,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() await self.dut.aio.host.Disconnect(connection=dut_ref) assert not await self.is_device_connected(self.ref_left, ref_dut, 5) assert_false(await self.is_device_connected(self.ref_left, ref_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -429,7 +423,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=ear) # DUT initiates connection to ref_device. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() return dut_ref, ref_dut Loading @@ -445,8 +438,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) # Verify the Refs are disconnected assert not await self.is_device_connected(self.ref_left, ref_left_dut, 5) assert not await self.is_device_connected(self.ref_right, ref_right_dut, 5) assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -468,11 +461,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() await self.ref_left.aio.host.Disconnect(connection=ref_dut) assert not await self.is_device_connected(self.dut, dut_ref, 5) assert_false(await self.is_device_connected(self.dut, dut_ref, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM, 0), Loading Loading @@ -534,7 +526,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_res.result_variant(), 'connection') dut_ref, ref_dut = dut_ref_res.connection, ref_dut_res.connection assert dut_ref, ref_dut assert_is_not_none(dut_ref) assert dut_ref # Pairing (secure, wait_security) = await asyncio.gather( Loading @@ -548,7 +541,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref_dut = (await anext(aiter(advertisement))).connection advertisement.cancel() assert ref_dut @avatar.parameterized( (RANDOM, RANDOM, Ear.LEFT), Loading @@ -572,30 +564,28 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref_device=self.ref_left, ref_address_type=ref_address_type, ear=Ear.LEFT ) ref_left = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref_left, ref_left_dut = await self.dut_connect_to_ref( _, ref_left_dut = await self.dut_connect_to_ref( advertisement=advertisement_left, ref=ref_left, dut_address_type=dut_address_type ) advertisement_left.cancel() assert dut_ref_left, ref_left_dut advertisement_right = await self.ref_advertise_asha( ref_device=self.ref_right, ref_address_type=ref_address_type, ear=Ear.RIGHT ) ref_right = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.RIGHT) dut_ref_right, ref_right_dut = await self.dut_connect_to_ref( _, ref_right_dut = await self.dut_connect_to_ref( advertisement=advertisement_right, ref=ref_right, dut_address_type=dut_address_type ) advertisement_right.cancel() assert dut_ref_right, ref_right_dut if disconnect_device == Ear.LEFT: await self.ref_left.aio.host.Disconnect(connection=ref_left_dut) assert await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert not await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_true(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") else: await self.ref_right.aio.host.Disconnect(connection=ref_right_dut) assert not await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") assert_true(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM, Ear.LEFT), Loading Loading @@ -625,7 +615,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_left_res.result_variant(), 'connection') dut_ref_left, ref_left_dut = dut_ref_left_res.connection, ref_left_dut_res.connection assert dut_ref_left, ref_left_dut assert_is_not_none(dut_ref_left) assert dut_ref_left advertisement_left.cancel() advertisement_right = await self.ref_advertise_asha( Loading @@ -638,7 +629,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_right_res.result_variant(), 'connection') dut_ref_right, ref_right_dut = dut_ref_right_res.connection, ref_right_dut_res.connection assert dut_ref_right, ref_right_dut assert_is_not_none(dut_ref_right) assert dut_ref_right advertisement_right.cancel() # Pairing Loading @@ -661,27 +653,25 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] self.ref_left.aio.host.Disconnect(connection=ref_left_dut), self.dut.aio.host.WaitDisconnection(connection=dut_ref_left), ) assert not await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") advertisement_left = await self.ref_advertise_asha( ref_device=self.ref_left, ref_address_type=ref_address_type, ear=Ear.LEFT ) ref_left_dut = (await anext(aiter(advertisement_left))).connection advertisement_left.cancel() assert ref_left_dut else: await asyncio.gather( self.ref_right.aio.host.Disconnect(connection=ref_right_dut), self.dut.aio.host.WaitDisconnection(connection=dut_ref_right), ) assert not await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") advertisement_right = await self.ref_advertise_asha( ref_device=self.ref_right, ref_address_type=ref_address_type, ear=Ear.RIGHT ) ref_right_dut = (await anext(aiter(advertisement_right))).connection advertisement_right.cancel() assert ref_right_dut @asynchronous async def test_music_start(self) -> None: Loading @@ -698,8 +688,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=RANDOM, ear=Ear.LEFT) # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut dut_ref, _ = await self.dut_connect_to_ref(advertisement, ref, RANDOM) asha_service = next((x for x in self.ref_left.device.gatt_server.attributes if isinstance(x, AshaGattService))) Loading @@ -724,10 +713,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await self.dut.aio.security.Secure(connection=dut_ref, le=LE_LEVEL3) le_psm_out_result = await asyncio.wait_for(le_psm_future, timeout=3.0) assert le_psm_out_result is not None assert_is_not_none(le_psm_out_result) read_only_properties_result = await asyncio.wait_for(read_only_properties_future, timeout=3.0) assert read_only_properties_result is not None assert_is_not_none(read_only_properties_result) dut_asha = AioAsha(self.dut.aio.channel) Loading @@ -745,12 +734,12 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) logging.info(f"start_result:{start_result}") assert start_result is not None assert isinstance(start_result, dict) assert start_result['codec'] == 1 assert start_result['audiotype'] == 0 assert start_result['volume'] is not None assert start_result['otherstate'] == 0 assert_is_not_none(start_result) assert_true(isinstance(start_result, dict), "") assert_equal(start_result['codec'], 1) assert_equal(start_result['audiotype'], 0) assert_is_not_none(start_result['volume']) assert_equal(start_result['otherstate'], 0) @asynchronous async def test_set_volume(self) -> None: Loading @@ -770,7 +759,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -792,8 +780,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, volume_result = await asyncio.gather(dut_asha.SetVolume(1), asyncio.wait_for(volume_future, timeout=3.0)) logging.info(f"start_result:{volume_result}") assert volume_result is not None assert volume_result == 0 # Android max volume's value is 0 assert_is_not_none(volume_result) assert_equal(volume_result, 0) @asynchronous async def test_music_stop(self) -> None: Loading @@ -811,7 +799,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -833,7 +820,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, stop_result = await asyncio.gather(dut_asha.Stop(), asyncio.wait_for(stop_future, timeout=10.0)) logging.info(f"stop_result:{stop_result}") assert stop_result is not None assert_is_not_none(stop_result) ref_asha = AioAsha(self.ref_left.aio.channel) try: Loading Loading @@ -861,8 +848,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=RANDOM, ear=Ear.LEFT) # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut dut_ref, _ = await self.dut_connect_to_ref(advertisement, ref, RANDOM) # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -883,7 +869,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, stop_result = await asyncio.gather(dut_asha.Stop(), asyncio.wait_for(stop_future, timeout=10.0)) logging.info(f"stop_result:{stop_result}") assert stop_result is not None assert_is_not_none(stop_result) # restart music streaming logging.info("restart music streaming") Loading @@ -901,7 +887,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) logging.info(f"start_result:{start_result}") assert start_result is not None assert_is_not_none(start_result) if __name__ == "__main__": Loading Loading
android/pandora/mmi2grpc/mmi2grpc/gatt.py +15 −16 Original line number Diff line number Diff line Loading @@ -61,16 +61,18 @@ MMI_SERVER = { "GATT/SR/GAD/BV-01-C", } BASE_UUID = "0000XXXX-0000-1000-8000-00805F9B34FB" # These UUIDs are used as reference for GATT server tests BASE_READ_WRITE_SERVICE_UUID = "0000fffe-0000-1000-8000-00805f9b34fb" BASE_READ_CHARACTERISTIC_UUID = "0000ffd-0000-1000-8000-00805f9b34fb" BASE_WRITE_CHARACTERISTIC_UUID = "0000fffa-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_ENCRYPTED_CHARACTERISTIC_UUID = "0000fff9-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_ENCRYPTED_MITM_CHARACTERISTIC_UUID = "0000fff8-0000-1000-8000-00805f9b34fb" BASE_READ_DESCRIPTOR_UUID = "0000fff7-0000-1000-8000-00805f9b34fb" BASE_WRITE_DESCRIPTOR_UUID = "0000fff6-0000-1000-8000-00805f9b34fb" CUSTOM_SERVICE_UUID = "0000fff5-0000-1000-8000-00805f9b34fb" CUSTOM_CHARACTERISTIC_UUID = "0000fff4-0000-1000-8000-00805f9b34fb" BASE_READ_WRITE_SERVICE_UUID = "0000FFFE-0000-1000-8000-00805F9B34FB" BASE_READ_CHARACTERISTIC_UUID = "0000FFD-0000-1000-8000-00805F9B34FB" BASE_WRITE_CHARACTERISTIC_UUID = "0000FFFA-0000-1000-8000-00805F9B34FB" BASE_READ_WRITE_ENCRYPTED_CHARACTERISTIC_UUID = "0000FFF9-0000-1000-8000-00805F9B34FB" BASE_READ_WRITE_ENCRYPTED_MITM_CHARACTERISTIC_UUID = "0000FFF8-0000-1000-8000-00805F9B34FB" BASE_READ_DESCRIPTOR_UUID = "0000FFF7-0000-1000-8000-00805F9B34FB" BASE_WRITE_DESCRIPTOR_UUID = "0000FFF6-0000-1000-8000-00805F9B34FB" CUSTOM_SERVICE_UUID = "0000FFF5-0000-1000-8000-00805F9B34FB" CUSTOM_CHARACTERISTIC_UUID = "0000FFF4-0000-1000-8000-00805F9B34FB" class GATTProxy(ProfileProxy): Loading Loading @@ -1302,9 +1304,6 @@ class GATTProxy(ProfileProxy): return "OK" common_uuid = "0000XXXX-0000-1000-8000-00805f9b34fb" def stringHandleToInt(handle: str): return int(handle, 16) Loading @@ -1325,23 +1324,23 @@ def formatUuid(uuid: str): """ uuid_len = len(uuid) if uuid_len == 4: return common_uuid.replace(common_uuid[4:8], uuid.lower()) return BASE_UUID.replace(BASE_UUID[4:8], uuid.upper()) elif uuid_len == 32 or uuid_len == 39: uuidCharList = list(uuid.replace('-', '').lower()) uuidCharList = list(uuid.replace('-', '').upper()) uuidCharList.insert(20, '-') uuidCharList.insert(16, '-') uuidCharList.insert(12, '-') uuidCharList.insert(8, '-') return ''.join(uuidCharList) else: return uuid return uuid.upper() # PTS asks wrong uuid for services discovered by SDP in some tests def formatSdpUuid(uuid: str): if uuid[3] == '1': uuid = uuid[:3] + 'f' return common_uuid.replace(common_uuid[4:8], uuid.lower()) return BASE_UUID.replace(BASE_UUID[4:8], uuid.upper()) def compareIncludedServices(service, service_handle, included_handle, included_uuid): Loading
android/pandora/server/src/com/android/pandora/Gatt.kt +5 −5 Original line number Diff line number Diff line Loading @@ -161,7 +161,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { .first() val uuidsList = arrayListOf<String>() for (parcelUuid in bluetoothDevice.getUuids()) { uuidsList.add(parcelUuid.toString()) uuidsList.add(parcelUuid.toString().uppercase()) } DiscoverServicesSdpResponse.newBuilder().addAllServiceUuids(uuidsList).build() } Loading Loading @@ -268,7 +268,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattService.newBuilder() .setHandle(fullService.instanceId) .setType(fullService.type) .setUuid(fullService.uuid.toString()) .setUuid(fullService.uuid.toString().uppercase()) .addAllIncludedServices(generateServicesList(service.includedServices, 1)) .addAllCharacteristics(generateCharacteristicsList(service.characteristics)) .build() Loading Loading @@ -379,7 +379,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattService.newBuilder() .setHandle(service.getInstanceId()) .setType(service.getType()) .setUuid(service.getUuid().toString()) .setUuid(service.getUuid().toString().uppercase()) .addAllIncludedServices(generateServicesList(service.getIncludedServices(), dpth + 1)) .addAllCharacteristics(generateCharacteristicsList(service.characteristics)) newServicesList.add(serviceBuilder.build()) Loading @@ -397,7 +397,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattCharacteristic.newBuilder() .setProperties(characteristic.getProperties()) .setPermissions(characteristic.getPermissions()) .setUuid(characteristic.getUuid().toString()) .setUuid(characteristic.getUuid().toString().uppercase()) .addAllDescriptors(generateDescriptorsList(characteristic.getDescriptors())) .setHandle(characteristic.getInstanceId()) newCharacteristicsList.add(characteristicBuilder.build()) Loading @@ -415,7 +415,7 @@ class Gatt(private val context: Context) : GATTImplBase(), Closeable { GattCharacteristicDescriptor.newBuilder() .setHandle(descriptor.getInstanceId()) .setPermissions(descriptor.getPermissions()) .setUuid(descriptor.getUuid().toString()) .setUuid(descriptor.getUuid().toString().uppercase()) newDescriptorsList.add(descriptorBuilder.build()) } return newDescriptorsList Loading
android/pandora/server/src/com/android/pandora/GattInstance.kt +1 −1 Original line number Diff line number Diff line Loading @@ -162,7 +162,7 @@ class GattInstance(val mDevice: BluetoothDevice, val mTransport: Int, val mConte characteristic: BluetoothGattCharacteristic, value: ByteArray ) { Log.i(TAG, "onCharacteristicChanged, characteristic: " + characteristic.getUuid().toString()) Log.i(TAG, "onCharacteristicChanged, characteristic: " + characteristic.getUuid().toString().uppercase()) mCharacteristicChangedMap[characteristic] = true mOnCharacteristicChanged.value = true } Loading
android/pandora/server/src/com/android/pandora/Host.kt +3 −3 Original line number Diff line number Diff line Loading @@ -648,7 +648,7 @@ class Host( for (serviceDataEntry in serviceData) { val parcelUuid = serviceDataEntry.key Log.d(TAG, parcelUuid.uuid.toString()) Log.d(TAG, parcelUuid.uuid.toString().uppercase()) // use upper case uuid as the key if (BluetoothUuid.is16BitUuid(parcelUuid)) { Loading @@ -673,7 +673,7 @@ class Host( } for (serviceUuid in scanRecord.serviceSolicitationUuids ?: listOf<ParcelUuid>()) { Log.d(TAG, serviceUuid.uuid.toString()) Log.d(TAG, serviceUuid.uuid.toString().uppercase()) if (BluetoothUuid.is16BitUuid(serviceUuid)) { val uuid16 = serviceUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addServiceSolicitationUuids16(uuid16) Loading @@ -687,7 +687,7 @@ class Host( } for (serviceUuid in scanRecord.serviceUuids ?: listOf<ParcelUuid>()) { Log.d(TAG, serviceUuid.uuid.toString()) Log.d(TAG, serviceUuid.uuid.toString().uppercase()) if (BluetoothUuid.is16BitUuid(serviceUuid)) { val uuid16 = serviceUuid.uuid.toString().substring(4, 8).uppercase() dataTypesBuilder.addIncompleteServiceClassUuids16(uuid16) Loading
android/pandora/test/asha_test.py +49 −63 Original line number Diff line number Diff line Loading @@ -20,19 +20,21 @@ import logging from avatar import BumblePandoraDevice, PandoraDevice, PandoraDevices, asynchronous, bumble_server from bumble.gatt import GATT_ASHA_SERVICE from bumble.smp import PairingDelegate from bumble.pairing import PairingDelegate from bumble_experimental.asha import AshaGattService, AshaService from mobly import base_test, signals, test_runner from mobly.asserts import assert_equal # type: ignore from mobly.asserts import assert_false # type: ignore from mobly.asserts import assert_in # type: ignore from mobly.asserts import skip # type: ignore from mobly.asserts import assert_is_not_none # type: ignore from mobly.asserts import assert_true # type: ignore from pandora._utils import AioStream from pandora.host_pb2 import PUBLIC, RANDOM, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse from pandora.security_pb2 import LE_LEVEL3 from pandora_experimental.asha_grpc_aio import Asha as AioAsha, add_AshaServicer_to_server from typing import List, Optional, Tuple ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str() ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str('-') HISYCNID: List[int] = [0x01, 0x02, 0x03, 0x04, 0x5, 0x6, 0x7, 0x8] COMPLETE_LOCAL_NAME: str = "Bumble" AUDIO_SIGNAL_AMPLITUDE = 0.8 Loading @@ -45,9 +47,6 @@ class Ear(enum.IntEnum): LEFT = 0 RIGHT = 1 def __repr__(self) -> str: return str(self.value) class ASHATest(base_test.BaseTestClass): # type: ignore[misc] devices: Optional[PandoraDevices] = None Loading @@ -60,18 +59,18 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] def setup_class(self) -> None: # Register experimental bumble servicers hook. bumble_server.register_servicer_hook( lambda bumble, server: add_AshaServicer_to_server(AshaService(bumble.device), server) lambda bumble, _, server: add_AshaServicer_to_server(AshaService(bumble.device), server) ) self.devices = PandoraDevices(self) self.dut, ref_left, ref_right, *_ = self.devices if isinstance(self.dut, BumblePandoraDevice): raise signals.TestAbortAll('DUT Bumble does not support Asha source') raise signals.TestAbortClass('DUT Bumble does not support Asha source') if not isinstance(ref_left, BumblePandoraDevice): raise signals.TestAbortAll('Test require Bumble as reference device(s)') raise signals.TestAbortClass('Test require Bumble as reference device(s)') if not isinstance(ref_right, BumblePandoraDevice): raise signals.TestAbortAll('Test require Bumble as reference device(s)') raise signals.TestAbortClass('Test require Bumble as reference device(s)') self.ref_left, self.ref_right = ref_left, ref_right Loading @@ -84,8 +83,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await asyncio.gather(self.dut.reset(), self.ref_left.reset(), self.ref_right.reset()) # ASHA hearing aid's IO capability is NO_OUTPUT_NO_INPUT setattr(self.ref_left.device, "io_capability", PairingDelegate.NO_OUTPUT_NO_INPUT) setattr(self.ref_right.device, "io_capability", PairingDelegate.NO_OUTPUT_NO_INPUT) self.ref_left.server_config.io_capability = PairingDelegate.NO_OUTPUT_NO_INPUT self.ref_right.server_config.io_capability = PairingDelegate.NO_OUTPUT_NO_INPUT async def ref_advertise_asha( self, ref_device: PandoraDevice, ref_address_type: OwnAddressType, ear: Ear Loading Loading @@ -125,7 +124,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) ) dut_scan.cancel() assert ref return ref async def dut_connect_to_ref( Loading @@ -141,9 +139,9 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_res.result_variant(), 'connection') dut_ref, ref_dut = dut_ref_res.connection, ref_dut_res.connection assert dut_ref and ref_dut assert_is_not_none(dut_ref) assert dut_ref advertisement.cancel() return dut_ref, ref_dut async def is_device_connected(self, device: PandoraDevice, connection: Connection, timeout: float) -> bool: Loading @@ -151,7 +149,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await device.aio.host.WaitDisconnection(connection=connection, timeout=timeout) return False except grpc.RpcError as e: assert e.code() == grpc.StatusCode.DEADLINE_EXCEEDED # type: ignore assert_equal(e.code(), grpc.StatusCode.DEADLINE_EXCEEDED) # type: ignore return True def get_expected_advertisement_data(self, ear: Ear) -> str: Loading Loading @@ -246,7 +244,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut # DUT starts pairing with the Ref. (secure, wait_security) = await asyncio.gather( Loading Loading @@ -280,7 +277,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=ear) # DUT initiates connection to ref_device. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() return dut_ref, ref_dut Loading Loading @@ -356,7 +352,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] logging.debug("result should come out") advertisement.cancel() assert dut_ref assert_is_not_none(dut_ref) secure = await self.dut.aio.security.Secure(connection=dut_ref, le=LE_LEVEL3) Loading @@ -378,8 +374,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut _, _ = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -401,11 +396,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() await self.dut.aio.host.Disconnect(connection=dut_ref) assert not await self.is_device_connected(self.ref_left, ref_dut, 5) assert_false(await self.is_device_connected(self.ref_left, ref_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -429,7 +423,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=ear) # DUT initiates connection to ref_device. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() return dut_ref, ref_dut Loading @@ -445,8 +438,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) # Verify the Refs are disconnected assert not await self.is_device_connected(self.ref_left, ref_left_dut, 5) assert not await self.is_device_connected(self.ref_right, ref_right_dut, 5) assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM), Loading @@ -468,11 +461,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, dut_address_type) assert dut_ref, ref_dut advertisement.cancel() await self.ref_left.aio.host.Disconnect(connection=ref_dut) assert not await self.is_device_connected(self.dut, dut_ref, 5) assert_false(await self.is_device_connected(self.dut, dut_ref, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM, 0), Loading Loading @@ -534,7 +526,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_res.result_variant(), 'connection') dut_ref, ref_dut = dut_ref_res.connection, ref_dut_res.connection assert dut_ref, ref_dut assert_is_not_none(dut_ref) assert dut_ref # Pairing (secure, wait_security) = await asyncio.gather( Loading @@ -548,7 +541,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref_dut = (await anext(aiter(advertisement))).connection advertisement.cancel() assert ref_dut @avatar.parameterized( (RANDOM, RANDOM, Ear.LEFT), Loading @@ -572,30 +564,28 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref_device=self.ref_left, ref_address_type=ref_address_type, ear=Ear.LEFT ) ref_left = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.LEFT) dut_ref_left, ref_left_dut = await self.dut_connect_to_ref( _, ref_left_dut = await self.dut_connect_to_ref( advertisement=advertisement_left, ref=ref_left, dut_address_type=dut_address_type ) advertisement_left.cancel() assert dut_ref_left, ref_left_dut advertisement_right = await self.ref_advertise_asha( ref_device=self.ref_right, ref_address_type=ref_address_type, ear=Ear.RIGHT ) ref_right = await self.dut_scan_for_asha(dut_address_type=dut_address_type, ear=Ear.RIGHT) dut_ref_right, ref_right_dut = await self.dut_connect_to_ref( _, ref_right_dut = await self.dut_connect_to_ref( advertisement=advertisement_right, ref=ref_right, dut_address_type=dut_address_type ) advertisement_right.cancel() assert dut_ref_right, ref_right_dut if disconnect_device == Ear.LEFT: await self.ref_left.aio.host.Disconnect(connection=ref_left_dut) assert await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert not await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_true(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") else: await self.ref_right.aio.host.Disconnect(connection=ref_right_dut) assert not await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") assert_true(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") @avatar.parameterized( (RANDOM, RANDOM, Ear.LEFT), Loading Loading @@ -625,7 +615,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_left_res.result_variant(), 'connection') dut_ref_left, ref_left_dut = dut_ref_left_res.connection, ref_left_dut_res.connection assert dut_ref_left, ref_left_dut assert_is_not_none(dut_ref_left) assert dut_ref_left advertisement_left.cancel() advertisement_right = await self.ref_advertise_asha( Loading @@ -638,7 +629,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) assert_equal(dut_ref_right_res.result_variant(), 'connection') dut_ref_right, ref_right_dut = dut_ref_right_res.connection, ref_right_dut_res.connection assert dut_ref_right, ref_right_dut assert_is_not_none(dut_ref_right) assert dut_ref_right advertisement_right.cancel() # Pairing Loading @@ -661,27 +653,25 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] self.ref_left.aio.host.Disconnect(connection=ref_left_dut), self.dut.aio.host.WaitDisconnection(connection=dut_ref_left), ) assert not await self.is_device_connected(device=self.ref_left, connection=ref_left_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_left, ref_left_dut, 5), "Should be disconnected") advertisement_left = await self.ref_advertise_asha( ref_device=self.ref_left, ref_address_type=ref_address_type, ear=Ear.LEFT ) ref_left_dut = (await anext(aiter(advertisement_left))).connection advertisement_left.cancel() assert ref_left_dut else: await asyncio.gather( self.ref_right.aio.host.Disconnect(connection=ref_right_dut), self.dut.aio.host.WaitDisconnection(connection=dut_ref_right), ) assert not await self.is_device_connected(device=self.ref_right, connection=ref_right_dut, timeout=5.0) assert_false(await self.is_device_connected(self.ref_right, ref_right_dut, 5), "Should be disconnected") advertisement_right = await self.ref_advertise_asha( ref_device=self.ref_right, ref_address_type=ref_address_type, ear=Ear.RIGHT ) ref_right_dut = (await anext(aiter(advertisement_right))).connection advertisement_right.cancel() assert ref_right_dut @asynchronous async def test_music_start(self) -> None: Loading @@ -698,8 +688,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=RANDOM, ear=Ear.LEFT) # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut dut_ref, _ = await self.dut_connect_to_ref(advertisement, ref, RANDOM) asha_service = next((x for x in self.ref_left.device.gatt_server.attributes if isinstance(x, AshaGattService))) Loading @@ -724,10 +713,10 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] await self.dut.aio.security.Secure(connection=dut_ref, le=LE_LEVEL3) le_psm_out_result = await asyncio.wait_for(le_psm_future, timeout=3.0) assert le_psm_out_result is not None assert_is_not_none(le_psm_out_result) read_only_properties_result = await asyncio.wait_for(read_only_properties_future, timeout=3.0) assert read_only_properties_result is not None assert_is_not_none(read_only_properties_result) dut_asha = AioAsha(self.dut.aio.channel) Loading @@ -745,12 +734,12 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) logging.info(f"start_result:{start_result}") assert start_result is not None assert isinstance(start_result, dict) assert start_result['codec'] == 1 assert start_result['audiotype'] == 0 assert start_result['volume'] is not None assert start_result['otherstate'] == 0 assert_is_not_none(start_result) assert_true(isinstance(start_result, dict), "") assert_equal(start_result['codec'], 1) assert_equal(start_result['audiotype'], 0) assert_is_not_none(start_result['volume']) assert_equal(start_result['otherstate'], 0) @asynchronous async def test_set_volume(self) -> None: Loading @@ -770,7 +759,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -792,8 +780,8 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, volume_result = await asyncio.gather(dut_asha.SetVolume(1), asyncio.wait_for(volume_future, timeout=3.0)) logging.info(f"start_result:{volume_result}") assert volume_result is not None assert volume_result == 0 # Android max volume's value is 0 assert_is_not_none(volume_result) assert_equal(volume_result, 0) @asynchronous async def test_music_stop(self) -> None: Loading @@ -811,7 +799,6 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -833,7 +820,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, stop_result = await asyncio.gather(dut_asha.Stop(), asyncio.wait_for(stop_future, timeout=10.0)) logging.info(f"stop_result:{stop_result}") assert stop_result is not None assert_is_not_none(stop_result) ref_asha = AioAsha(self.ref_left.aio.channel) try: Loading Loading @@ -861,8 +848,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = await self.dut_scan_for_asha(dut_address_type=RANDOM, ear=Ear.LEFT) # DUT initiates connection to Ref. dut_ref, ref_dut = await self.dut_connect_to_ref(advertisement, ref, RANDOM) assert dut_ref, ref_dut dut_ref, _ = await self.dut_connect_to_ref(advertisement, ref, RANDOM) # DUT starts pairing with the Ref. # FIXME: assert the security Level on ref side Loading @@ -883,7 +869,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] _, stop_result = await asyncio.gather(dut_asha.Stop(), asyncio.wait_for(stop_future, timeout=10.0)) logging.info(f"stop_result:{stop_result}") assert stop_result is not None assert_is_not_none(stop_result) # restart music streaming logging.info("restart music streaming") Loading @@ -901,7 +887,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ) logging.info(f"start_result:{start_result}") assert start_result is not None assert_is_not_none(start_result) if __name__ == "__main__": Loading