blob: 37cf0a12fdf6cf1ac03d7d02b8afae72e46dc1f2 [file]
/*
* Copyright (C) 2026 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 android.bluetooth;
import android.annotation.FlaggedApi;
import android.annotation.Hide;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresNoPermission;
import static java.util.Objects.requireNonNull;
import android.annotation.SuppressLint;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.bluetooth.flags.Flags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Represents the state of a Bluetooth LE Broadcast Sink for a specific broadcast source.
*
* <p>This object provides brief information about a broadcast's current state. It includes the
* sink's current PA and BIG sync states, as well as BIS sync states to show which BIS are currently
* active.
*/
@Hide
@FlaggedApi(Flags.FLAG_LEAUDIO_BROADCAST_SINK_FEATURE)
public final class BluetoothLeBroadcastSinkState {
private final InnerParcel mParcel;
/**
* Constructor for a {@link BluetoothLeBroadcastSinkState}.
*
* @param broadcastId The broadcast ID of the source.
* @param paSyncState The PA sync state for the broadcast source.
* @param bigSyncState The BIG sync state for the broadcast source.
* @param bisSyncStates A list of bitfields representing the synchronization state of each BIS.
*/
@Hide
public BluetoothLeBroadcastSinkState(
int broadcastId,
@PaSyncState int paSyncState,
@BigSyncState int bigSyncState,
@NonNull List<Long> bisSyncStates) {
mParcel = new InnerParcel(broadcastId, paSyncState, bigSyncState, bisSyncStates);
}
/**
* Private constructor to create a {@link BluetoothLeBroadcastSinkState} from an InnerParcel.
*
* @param parcel The InnerParcel containing the state data.
*/
private BluetoothLeBroadcastSinkState(InnerParcel parcel) {
mParcel = parcel;
}
/**
* Get the underlying parcelable object.
*
* @return The InnerParcel object.
*/
@Hide
@RequiresNoPermission
public InnerParcel getParcel() {
return mParcel;
}
/**
* Create a {@link BluetoothLeBroadcastSinkState} from an InnerParcel.
*
* @param parcel The InnerParcel to create the state from.
* @return the {@link BluetoothLeBroadcastSinkState} associated with this parcel, or null if the
* parcel is null.
*/
@RequiresNoPermission
static @Nullable BluetoothLeBroadcastSinkState fromParcel(InnerParcel parcel) {
if (parcel == null) {
return null;
}
return new BluetoothLeBroadcastSinkState(parcel);
}
/** The overall PA state of the Broadcast Sink for a given source. */
@Hide
@IntDef(
prefix = "SINK_PA_STATE_",
value = {
SINK_PA_STATE_IDLE,
SINK_PA_STATE_SYNCING,
SINK_PA_STATE_SYNCED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PaSyncState {}
/** The sink is not tracking or synchronizing with the PA of this source. */
public static final int SINK_PA_STATE_IDLE = 0;
/** The sink is attempting to synchronize with the PA of this source. */
public static final int SINK_PA_STATE_SYNCING = 1;
/** The sink is synchronized with the PA of this source. */
public static final int SINK_PA_STATE_SYNCED = 2;
/** The overall BIG state of the Broadcast Sink for a given source. */
@IntDef(
prefix = "SINK_BIG_STATE_",
value = {
SINK_BIG_STATE_IDLE,
SINK_BIG_STATE_SYNCING,
SINK_BIG_STATE_SYNCED,
SINK_BIG_STATE_LEAVING,
SINK_BIG_STATE_UPDATING,
})
@Retention(RetentionPolicy.SOURCE)
public @interface BigSyncState {}
/**
* The sink is not attempting to join or is not joined to the BIG. This is the default state.
*/
public static final int SINK_BIG_STATE_IDLE = 0;
/** The sink is attempting to synchronize with the BIG to receive audio. */
public static final int SINK_BIG_STATE_SYNCING = 1;
/** The sink is synchronized with the BIG and receiving audio. */
public static final int SINK_BIG_STATE_SYNCED = 2;
/** The sink was terminating BIG sync to stop receiving audio. */
public static final int SINK_BIG_STATE_LEAVING = 3;
/** The sink was updating BIG sync to change subgroup. */
public static final int SINK_BIG_STATE_UPDATING = 4;
/**
* Get the broadcast ID of the source.
*
* @return the broadcast ID of the source
*/
@Hide
@RequiresNoPermission
public int getBroadcastId() {
return mParcel.mBroadcastId;
}
/**
* Get the PA sync state for the broadcast source.
*
* @return the PA sync state
*/
@Hide
@RequiresNoPermission
public @PaSyncState int getPaSyncState() {
return mParcel.mPaSyncState;
}
/**
* Get the BIG sync state for the broadcast source.
*
* @return the BIG sync state
*/
@Hide
@RequiresNoPermission
public @BigSyncState int getBigSyncState() {
return mParcel.mBigSyncState;
}
/**
* Get a list of bitfields representing the synchronization state of each BIS. value 0 means the
* BIS is not synchronized. value 1 means the BIS is synchronized.
*
* @return a list of BIS synchronization states
*/
@Hide
@RequiresNoPermission
public @NonNull List<Long> getBisSyncStates() {
return mParcel.mBisSyncStates;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (!(o instanceof BluetoothLeBroadcastSinkState)) return false;
BluetoothLeBroadcastSinkState that = (BluetoothLeBroadcastSinkState) o;
return Objects.equals(mParcel, that.mParcel);
}
@Override
public int hashCode() {
return Objects.hash(mParcel);
}
/**
* Returns a string representation of this BluetoothLeBroadcastSinkState object.
*
* @return a string representation of this object
*/
@Override
public String toString() {
return "BluetoothLeBroadcastSinkState{"
+ "mBroadcastId="
+ getBroadcastId()
+ ", mPaSyncState="
+ getPaSyncState()
+ ", mBigSyncState="
+ getBigSyncState()
+ ", mBisSyncStates="
+ getBisSyncStates()
+ '}';
}
public static final class InnerParcel implements Parcelable {
private final int mBroadcastId;
private final @PaSyncState int mPaSyncState;
private final @BigSyncState int mBigSyncState;
private final List<Long> mBisSyncStates;
InnerParcel(
int broadcastId,
@PaSyncState int paSyncState,
@BigSyncState int bigSyncState,
@NonNull List<Long> bisSyncStates) {
mBroadcastId = broadcastId;
mPaSyncState = paSyncState;
mBigSyncState = bigSyncState;
mBisSyncStates = bisSyncStates;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (!(o instanceof InnerParcel)) return false;
InnerParcel that = (InnerParcel) o;
return mBroadcastId == that.mBroadcastId
&& mPaSyncState == that.mPaSyncState
&& mBigSyncState == that.mBigSyncState
&& Objects.equals(mBisSyncStates, that.mBisSyncStates);
}
@Override
public int hashCode() {
return Objects.hash(mBroadcastId, mPaSyncState, mBigSyncState, mBisSyncStates);
}
private InnerParcel(Parcel in) {
mBroadcastId = in.readInt();
mPaSyncState = in.readInt();
mBigSyncState = in.readInt();
mBisSyncStates =
requireNonNull(in.readArrayList(Long.class.getClassLoader(), Long.class));
}
@Override
public int describeContents() {
return 0;
}
@Override
@SuppressWarnings("AndroidFrameworkEfficientParcelable") // No Creator match List<Long>
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(mBroadcastId);
out.writeInt(mPaSyncState);
out.writeInt(mBigSyncState);
out.writeList(mBisSyncStates);
}
/** {@link Parcelable.Creator} interface implementation. */
public static final @NonNull Parcelable.Creator<InnerParcel> CREATOR =
new Parcelable.Creator<InnerParcel>() {
@Override
public @NonNull InnerParcel createFromParcel(Parcel in) {
return new InnerParcel(in);
}
@Override
public @NonNull InnerParcel[] newArray(int size) {
return new InnerParcel[size];
}
};
}
}