Skip to content
Snippets Groups Projects
Commit 8cc1ff3c authored by Rongxuan Liu's avatar Rongxuan Liu Committed by Android Build Cherrypicker Worker
Browse files

[Audiosharing] Update QR code format to follow BT SIG standard

Bug: 324655158
Test: atest com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExtTest
Test: manually tested with broadcast source and assistant by QR code
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4abfa5bed1a35a9a9b5ac54951296b3edde4ee9a)
Merged-In: I798666b89c4e3558c7528bace0346caf8218dc53
Change-Id: I798666b89c4e3558c7528bace0346caf8218dc53
parent ad60df61
No related branches found
No related tags found
No related merge requests found
......@@ -43,5 +43,5 @@ public final class BluetoothBroadcastUtils {
/**
* Bluetooth scheme.
*/
public static final String SCHEME_BT_BROADCAST_METADATA = "BT:";
public static final String SCHEME_BT_BROADCAST_METADATA = "BLUETOOTH:UUID:184F;";
}
......@@ -32,7 +32,7 @@ import org.junit.runner.RunWith
class BluetoothLeBroadcastMetadataExtTest {
@Test
fun toQrCodeString() {
fun toQrCodeString_encrypted() {
val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
setCodecId(0x6)
val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder().build()
......@@ -69,6 +69,37 @@ class BluetoothLeBroadcastMetadataExtTest {
assertThat(qrCodeString).isEqualTo(QR_CODE_STRING)
}
@Test
fun toQrCodeString_non_encrypted() {
val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
setCodecId(0x6)
val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder().build()
setContentMetadata(BluetoothLeAudioContentMetadata.Builder()
.build())
setCodecSpecificConfig(audioCodecConfigMetadata)
addChannel(BluetoothLeBroadcastChannel.Builder().apply {
setSelected(true)
setChannelIndex(1)
setCodecMetadata(audioCodecConfigMetadata)
}.build())
}.build()
val metadata = BluetoothLeBroadcastMetadata.Builder().apply {
setSourceDevice(DevicePublic, BluetoothDevice.ADDRESS_TYPE_PUBLIC)
setSourceAdvertisingSid(1)
setBroadcastId(0xDE51E9)
setBroadcastName("Hockey")
setAudioConfigQuality(BluetoothLeBroadcastMetadata.AUDIO_CONFIG_QUALITY_STANDARD)
setPaSyncInterval(0xFFFF)
setEncrypted(false)
addSubgroup(subgroup)
}.build()
val qrCodeString = metadata.toQrCodeString()
assertThat(qrCodeString).isEqualTo(QR_CODE_STRING_NON_ENCRYPTED)
}
@Test
fun toQrCodeString_NoChannelSelected() {
val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
......@@ -102,6 +133,7 @@ class BluetoothLeBroadcastMetadataExtTest {
addSubgroup(subgroup)
}.build()
// if no channel is selected, no preference(0xFFFFFFFFu) will be set in BIS
val qrCodeString = metadata.toQrCodeString()
val parsedMetadata =
......@@ -111,13 +143,11 @@ class BluetoothLeBroadcastMetadataExtTest {
assertThat(parsedMetadata.subgroups).isNotNull()
assertThat(parsedMetadata.subgroups.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels).isNotNull()
assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(2)
assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].hasChannelPreference()).isFalse()
// Input order does not matter due to parsing through bisMask
// placeholder channel with not selected
assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isFalse()
assertThat(parsedMetadata.subgroups[0].channels[1].channelIndex).isEqualTo(2)
assertThat(parsedMetadata.subgroups[0].channels[1].isSelected).isFalse()
}
@Test
......@@ -162,13 +192,11 @@ class BluetoothLeBroadcastMetadataExtTest {
assertThat(parsedMetadata.subgroups).isNotNull()
assertThat(parsedMetadata.subgroups.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels).isNotNull()
// Only selected channel can be recovered
assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(2)
// Only selected channel can be recovered, non-selected ones will be ignored
assertThat(parsedMetadata.subgroups[0].channels.size).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].hasChannelPreference()).isTrue()
assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(1)
assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isFalse()
assertThat(parsedMetadata.subgroups[0].channels[1].channelIndex).isEqualTo(2)
assertThat(parsedMetadata.subgroups[0].channels[1].isSelected).isTrue()
assertThat(parsedMetadata.subgroups[0].channels[0].channelIndex).isEqualTo(2)
assertThat(parsedMetadata.subgroups[0].channels[0].isSelected).isTrue()
}
@Test
......@@ -180,16 +208,34 @@ class BluetoothLeBroadcastMetadataExtTest {
assertThat(qrCodeString).isEqualTo(QR_CODE_STRING)
}
@Test
fun decodeAndEncodeAgain_sameString_non_encrypted() {
val metadata =
BluetoothLeBroadcastMetadataExt
.convertToBroadcastMetadata(QR_CODE_STRING_NON_ENCRYPTED)!!
val qrCodeString = metadata.toQrCodeString()
assertThat(qrCodeString).isEqualTo(QR_CODE_STRING_NON_ENCRYPTED)
}
private companion object {
const val TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"
const val TEST_DEVICE_ADDRESS_PUBLIC = "AA:BB:CC:00:11:22"
val Device: BluetoothDevice =
BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(TEST_DEVICE_ADDRESS,
BluetoothDevice.ADDRESS_TYPE_RANDOM)
val DevicePublic: BluetoothDevice =
BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(TEST_DEVICE_ADDRESS_PUBLIC,
BluetoothDevice.ADDRESS_TYPE_PUBLIC)
const val QR_CODE_STRING =
"BT:R:65536;T:1;D:00-A1-A1-A1-A1-A1;AS:1;B:123456;BN:VGVzdA==;" +
"PM:BgNwVGVzdA==;SI:160;C:VGVzdENvZGU=;SG:BS:3,BM:3,AC:BQNUZXN0BARlbmc=;" +
"VN:U;;"
"BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;" +
"MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;"
const val QR_CODE_STRING_NON_ENCRYPTED =
"BLUETOOTH:UUID:184F;BN:SG9ja2V5;AT:0;AD:AABBCC001122;BI:DE51E9;SQ:1;AS:1;PI:FFFF;" +
"NS:1;BS:1;NB:1;;"
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment