Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d50b00e authored by chelseahao's avatar chelseahao Committed by Chelsea Hao
Browse files

Create data class for private broadcast receive state intent.

Test: atest
Bug: 398700619
Flag: EXEMPT data class
Change-Id: I781ff4e3e24e7ede4c1503d5df56a32f7ef332e0
parent ca8d00d5
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+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)
        }
    }
}
+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
            )
    }
}