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

Commit 59973416 authored by Chelsea Hao's avatar Chelsea Hao Committed by Android (Google) Code Review
Browse files

Merge "Create data class for private broadcast receive state intent." into main

parents 61ddb0b0 6d50b00e
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
            )
    }
}