Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +3 −0 Original line number Diff line number Diff line Loading @@ -89,11 +89,14 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STATE_CHANGE"; public static final String ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED = "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_DEVICE_CONNECTED"; public static final String ACTION_LE_AUDIO_PRIVATE_BROADCAST_RECEIVED = "com.android.settings.action.BLUETOOTH_LE_AUDIO_PRIVATE_BROADCAST_RECEIVED"; public static final String EXTRA_LE_AUDIO_SHARING_STATE = "BLUETOOTH_LE_AUDIO_SHARING_STATE"; public static final String EXTRA_BLUETOOTH_DEVICE = "BLUETOOTH_DEVICE"; public static final String EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE = "BT_DEVICE_TO_AUTO_ADD_SOURCE"; public static final String EXTRA_START_LE_AUDIO_SHARING = "START_LE_AUDIO_SHARING"; public static final String EXTRA_PAIR_AND_JOIN_SHARING = "PAIR_AND_JOIN_SHARING"; public static final String EXTRA_PRIVATE_BROADCAST_RECEIVE_DATA = "RECEIVE_DATA"; public static final String BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID = "bluetooth_le_broadcast_primary_device_group_id"; public static final int BROADCAST_STATE_UNKNOWN = 0; Loading packages/SettingsLib/src/com/android/settingslib/bluetooth/PrivateBroadcastReceiveData.kt 0 → 100644 +90 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.BluetoothDevice import android.os.Parcel import android.os.Parcelable import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.STREAMING import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED /** * Data class representing information received in a private broadcast. * This class encapsulates details about the sink device, source ID, broadcast ID, and the * broadcast source state. * * @param sink The [BluetoothDevice] acting as the sink. * @param sourceId The ID of the audio source. * @param broadcastId The ID of the broadcast source. * @param programInfo The program info string of the broadcast source. * @param state The current state of the broadcast source. */ data class PrivateBroadcastReceiveData( val sink: BluetoothDevice?, val sourceId: Int = -1, val broadcastId: Int = -1, val programInfo: String = "", val state: LocalBluetoothLeBroadcastSourceState?, ) : Parcelable { override fun describeContents(): Int = 0 override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeParcelable(sink, flags) parcel.writeInt(sourceId) parcel.writeInt(broadcastId) parcel.writeString(programInfo) parcel.writeSerializable(state) } companion object { @JvmField val CREATOR: Parcelable.Creator<PrivateBroadcastReceiveData> = object : Parcelable.Creator<PrivateBroadcastReceiveData> { override fun createFromParcel(parcel: Parcel) = parcel.run { PrivateBroadcastReceiveData( sink = readParcelable( BluetoothDevice::class.java.classLoader, BluetoothDevice::class.java ), sourceId = readInt(), broadcastId = readInt(), programInfo = readString() ?: "", state = readSerializable( LocalBluetoothLeBroadcastSourceState::class.java.classLoader, LocalBluetoothLeBroadcastSourceState::class.java ) ) } override fun newArray(size: Int): Array<PrivateBroadcastReceiveData?> { return arrayOfNulls(size) } } fun PrivateBroadcastReceiveData.isValid(): Boolean { return sink != null && sourceId != -1 && broadcastId != -1 && (state == STREAMING || state == PAUSED || state == DECRYPTION_FAILED) } } } packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PrivateBroadcastReceiveDataTest.kt 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.os.Parcel import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState import com.android.settingslib.bluetooth.PrivateBroadcastReceiveData.Companion.isValid import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class PrivateBroadcastReceiveDataTest { @Test fun parcelable() { val original = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, programInfo = "Test Program", state = LocalBluetoothLeBroadcastSourceState.STREAMING ) val parcel = Parcel.obtain() original.writeToParcel(parcel, 0) parcel.setDataPosition(0) val recreated = PrivateBroadcastReceiveData.CREATOR.createFromParcel(parcel) assertEquals(original, recreated) } @Test fun isValid_validData() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertTrue(data.isValid()) } @Test fun isValid_nullSink() { val data = PrivateBroadcastReceiveData( sink = null, sourceId = 1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_invalidSourceId() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = -1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_invalidBroadcastId() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = -1, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_nullState() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, state = null ) assertFalse(data.isValid()) } @Test fun isValid_correctStates() { assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.STREAMING).isValid()) assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.PAUSED).isValid()) assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED).isValid()) } private companion object { const val TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1" val sink: BluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice( TEST_DEVICE_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM ) } } Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +3 −0 Original line number Diff line number Diff line Loading @@ -89,11 +89,14 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STATE_CHANGE"; public static final String ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED = "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_DEVICE_CONNECTED"; public static final String ACTION_LE_AUDIO_PRIVATE_BROADCAST_RECEIVED = "com.android.settings.action.BLUETOOTH_LE_AUDIO_PRIVATE_BROADCAST_RECEIVED"; public static final String EXTRA_LE_AUDIO_SHARING_STATE = "BLUETOOTH_LE_AUDIO_SHARING_STATE"; public static final String EXTRA_BLUETOOTH_DEVICE = "BLUETOOTH_DEVICE"; public static final String EXTRA_BT_DEVICE_TO_AUTO_ADD_SOURCE = "BT_DEVICE_TO_AUTO_ADD_SOURCE"; public static final String EXTRA_START_LE_AUDIO_SHARING = "START_LE_AUDIO_SHARING"; public static final String EXTRA_PAIR_AND_JOIN_SHARING = "PAIR_AND_JOIN_SHARING"; public static final String EXTRA_PRIVATE_BROADCAST_RECEIVE_DATA = "RECEIVE_DATA"; public static final String BLUETOOTH_LE_BROADCAST_PRIMARY_DEVICE_GROUP_ID = "bluetooth_le_broadcast_primary_device_group_id"; public static final int BROADCAST_STATE_UNKNOWN = 0; Loading
packages/SettingsLib/src/com/android/settingslib/bluetooth/PrivateBroadcastReceiveData.kt 0 → 100644 +90 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.BluetoothDevice import android.os.Parcel import android.os.Parcelable import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.PAUSED import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.STREAMING import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED /** * Data class representing information received in a private broadcast. * This class encapsulates details about the sink device, source ID, broadcast ID, and the * broadcast source state. * * @param sink The [BluetoothDevice] acting as the sink. * @param sourceId The ID of the audio source. * @param broadcastId The ID of the broadcast source. * @param programInfo The program info string of the broadcast source. * @param state The current state of the broadcast source. */ data class PrivateBroadcastReceiveData( val sink: BluetoothDevice?, val sourceId: Int = -1, val broadcastId: Int = -1, val programInfo: String = "", val state: LocalBluetoothLeBroadcastSourceState?, ) : Parcelable { override fun describeContents(): Int = 0 override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeParcelable(sink, flags) parcel.writeInt(sourceId) parcel.writeInt(broadcastId) parcel.writeString(programInfo) parcel.writeSerializable(state) } companion object { @JvmField val CREATOR: Parcelable.Creator<PrivateBroadcastReceiveData> = object : Parcelable.Creator<PrivateBroadcastReceiveData> { override fun createFromParcel(parcel: Parcel) = parcel.run { PrivateBroadcastReceiveData( sink = readParcelable( BluetoothDevice::class.java.classLoader, BluetoothDevice::class.java ), sourceId = readInt(), broadcastId = readInt(), programInfo = readString() ?: "", state = readSerializable( LocalBluetoothLeBroadcastSourceState::class.java.classLoader, LocalBluetoothLeBroadcastSourceState::class.java ) ) } override fun newArray(size: Int): Array<PrivateBroadcastReceiveData?> { return arrayOfNulls(size) } } fun PrivateBroadcastReceiveData.isValid(): Boolean { return sink != null && sourceId != -1 && broadcastId != -1 && (state == STREAMING || state == PAUSED || state == DECRYPTION_FAILED) } } }
packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PrivateBroadcastReceiveDataTest.kt 0 → 100644 +124 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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.os.Parcel import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant.LocalBluetoothLeBroadcastSourceState import com.android.settingslib.bluetooth.PrivateBroadcastReceiveData.Companion.isValid import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner @RunWith(RobolectricTestRunner::class) class PrivateBroadcastReceiveDataTest { @Test fun parcelable() { val original = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, programInfo = "Test Program", state = LocalBluetoothLeBroadcastSourceState.STREAMING ) val parcel = Parcel.obtain() original.writeToParcel(parcel, 0) parcel.setDataPosition(0) val recreated = PrivateBroadcastReceiveData.CREATOR.createFromParcel(parcel) assertEquals(original, recreated) } @Test fun isValid_validData() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertTrue(data.isValid()) } @Test fun isValid_nullSink() { val data = PrivateBroadcastReceiveData( sink = null, sourceId = 1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_invalidSourceId() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = -1, broadcastId = 2, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_invalidBroadcastId() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = -1, state = LocalBluetoothLeBroadcastSourceState.STREAMING ) assertFalse(data.isValid()) } @Test fun isValid_nullState() { val data = PrivateBroadcastReceiveData( sink = sink, sourceId = 1, broadcastId = 2, state = null ) assertFalse(data.isValid()) } @Test fun isValid_correctStates() { assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.STREAMING).isValid()) assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.PAUSED).isValid()) assertTrue(PrivateBroadcastReceiveData(sink, 1, 1, state = LocalBluetoothLeBroadcastSourceState.DECRYPTION_FAILED).isValid()) } private companion object { const val TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1" val sink: BluetoothDevice = BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice( TEST_DEVICE_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM ) } }