[LE Audio] New logic to generate the QR code
Currently the QR code string is generated in SettingsLib, and use
"<" and ">" to format the string.
Because the formatted string are multi layer nested, like
A:<B:<C:<<>;D:<>>;>;E:<F:<B:>;>;>;
Using Regex cannot handle this case,
- Regex cannot tell which B: is label for filed, which B: is user input
- Regex cannot tell which pair of <> is the correct open and close for B
- And these is no easy fix
The BluetoothLeBroadcastMetadata already implements the Parcelable
interface, use Parcel to serialize the string to fix issues.
Also, add unit test.
Fix: 248409874
Test: Unit test
Change-Id: I31ce4bb4f5e639deb0cb60ebd7d6bf904ae85788
diff --git a/packages/SettingsLib/tests/unit/Android.bp b/packages/SettingsLib/tests/unit/Android.bp
new file mode 100644
index 0000000..a4558f1
--- /dev/null
+++ b/packages/SettingsLib/tests/unit/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "SettingsLibUnitTests",
+ test_suites: ["device-tests"],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+
+ static_libs: [
+ "SettingsLib",
+ "androidx.test.ext.junit",
+ "androidx.test.runner",
+ "truth-prebuilt",
+ ],
+}
diff --git a/packages/SettingsLib/tests/unit/AndroidManifest.xml b/packages/SettingsLib/tests/unit/AndroidManifest.xml
new file mode 100644
index 0000000..568f9cb
--- /dev/null
+++ b/packages/SettingsLib/tests/unit/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.test">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Tests for SettingsLib"
+ android:targetPackage="com.android.settingslib.test">
+ </instrumentation>
+</manifest>
diff --git a/packages/SettingsLib/tests/unit/OWNERS b/packages/SettingsLib/tests/unit/OWNERS
new file mode 100644
index 0000000..66559252
--- /dev/null
+++ b/packages/SettingsLib/tests/unit/OWNERS
@@ -0,0 +1,2 @@
+# We do not guard tests - everyone is welcomed to contribute to tests.
+per-file *.kt=*
diff --git a/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt b/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt
new file mode 100644
index 0000000..0e3590d
--- /dev/null
+++ b/packages/SettingsLib/tests/unit/src/com/android/settingslib/bluetooth/BluetoothLeBroadcastMetadataExtTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.bluetooth
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothLeAudioCodecConfigMetadata
+import android.bluetooth.BluetoothLeAudioContentMetadata
+import android.bluetooth.BluetoothLeBroadcastChannel
+import android.bluetooth.BluetoothLeBroadcastMetadata
+import android.bluetooth.BluetoothLeBroadcastSubgroup
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt.toQrCodeString
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class BluetoothLeBroadcastMetadataExtTest {
+
+ @Test
+ fun toQrCodeString() {
+ val subgroup = BluetoothLeBroadcastSubgroup.Builder().apply {
+ setCodecId(100)
+ val audioCodecConfigMetadata = BluetoothLeAudioCodecConfigMetadata.Builder().build()
+ setCodecSpecificConfig(audioCodecConfigMetadata)
+ setContentMetadata(BluetoothLeAudioContentMetadata.Builder().build())
+ addChannel(BluetoothLeBroadcastChannel.Builder().apply {
+ setChannelIndex(1000)
+ setCodecMetadata(audioCodecConfigMetadata)
+ }.build())
+ }.build()
+
+ val metadata = BluetoothLeBroadcastMetadata.Builder().apply {
+ setSourceDevice(Device, 0)
+ setSourceAdvertisingSid(1)
+ setBroadcastId(2)
+ setPaSyncInterval(3)
+ setEncrypted(true)
+ setBroadcastCode(byteArrayOf(10, 11, 12, 13))
+ setPresentationDelayMicros(4)
+ addSubgroup(subgroup)
+ }.build()
+
+ val qrCodeString = metadata.toQrCodeString()
+
+ assertThat(qrCodeString).isEqualTo(QR_CODE_STRING)
+ }
+
+ @Test
+ fun decodeAndEncodeAgain_sameString() {
+ val metadata = BluetoothLeBroadcastMetadataExt.convertToBroadcastMetadata(QR_CODE_STRING)!!
+
+ val qrCodeString = metadata.toQrCodeString()
+
+ assertThat(qrCodeString).isEqualTo(QR_CODE_STRING)
+ }
+
+ private companion object {
+ const val TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1"
+
+ val Device: BluetoothDevice =
+ BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_DEVICE_ADDRESS)
+
+ const val QR_CODE_STRING =
+ "BT:BluetoothLeBroadcastMetadata:AAAAAAEAAAABAAAAEQAAADAAMAA6AEEAMQA6AEEAMQA6AEEAMQA6" +
+ "AEEAMQA6AEEAMQAAAAAAAAABAAAAAgAAAAMAAAABAAAABAAAAAQAAAAKCwwNBAAAAAEAAAABAAAAZAAA" +
+ "AAAAAAABAAAAAAAAAAAAAAAGAAAABgAAAAUDAAAAAAAAAAAAAAAAAAAAAAAAAQAAAP//////////AAAA" +
+ "AAAAAAABAAAAAQAAAAAAAADoAwAAAQAAAAAAAAAAAAAABgAAAAYAAAAFAwAAAAAAAAAAAAAAAAAAAAAA" +
+ "AAAAAAD/////AAAAAAAAAAA="
+ }
+}
\ No newline at end of file