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

Commit 251d9183 authored by Rongxuan Liu's avatar Rongxuan Liu
Browse files

[le audio] Add new APIs for broadcast metadata to set & get source RSSI

Flagged by: leaudio_broadcast_monitor_source_sync_status

Bug: 298665925
Bug: 307406671
Test: atest BluetoothLeBroadcastMetadataTest
Test: manual test callback with LeAudioTestApp
Change-Id: I96fac9b378f84afc3360c561b039b63b4a5df25e
parent 588c8e91
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -977,7 +977,8 @@ jobject prepareBluetoothLeBroadcastMetadataObject(
      broadcast_metadata.is_public, broadcast_name.get(),
      broadcast_metadata.broadcast_code ? code.get() : nullptr,
      (jint)broadcast_metadata.basic_audio_announcement.presentation_delay,
      audio_cfg_quality, public_meta_obj.get(), subgroup_list_obj.get());
      audio_cfg_quality, (jint)bluetooth::le_audio::kLeAudioSourceRssiUnknown,
      public_meta_obj.get(), subgroup_list_obj.get());
}

class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
@@ -1415,7 +1416,7 @@ static int register_com_android_bluetooth_le_audio_broadcaster(JNIEnv* env) {
  const JNIJavaMethod javaLeBroadcastMetadataMethods[] = {
      {"<init>",
       "(ILandroid/bluetooth/BluetoothDevice;IIIZZLjava/lang/String;"
       "[BIILandroid/bluetooth/BluetoothLeAudioContentMetadata;"
       "[BIIILandroid/bluetooth/BluetoothLeAudioContentMetadata;"
       "Ljava/util/List;)V",
       &android_bluetooth_BluetoothLeBroadcastMetadata.constructor},
  };
+7 −0
Original line number Diff line number Diff line
@@ -618,6 +618,13 @@ public class BassClientStateMachine extends StateMachine {
            }
        }
        metaData.setEncrypted(encrypted);
        if (mFeatureFlags.leaudioBroadcastMonitorSourceSyncStatus()) {
            // update the rssi value
            ScanResult scanRes = mService.getCachedBroadcast(result.getBroadcastId());
            if (scanRes != null) {
                metaData.setRssi(scanRes.getRssi());
            }
        }
        return metaData.build();
    }

+105 −0
Original line number Diff line number Diff line
@@ -1815,6 +1815,111 @@ public class BassClientStateMachineTest {
        verify(callbacks).notifySourceLost(broadcastId);
    }

    @Test
    public void periodicAdvertisingCallbackOnBigInfoAdvertisingReport_updateRssi() {
        mFakeFlagsImpl.setFlag(Flags.FLAG_LEAUDIO_BROADCAST_MONITOR_SOURCE_SYNC_STATUS, true);
        PeriodicAdvertisingCallback cb = mBassClientStateMachine.mLocalPeriodicAdvCallback;
        BassClientService.Callbacks callbacks = Mockito.mock(BassClientService.Callbacks.class);
        int testRssi = -40;
        int syncHandle = 1;
        final String testMacAddress = "00:11:22:33:44:55";
        BluetoothDevice testDevice =
                mAdapter.getRemoteLeDevice(testMacAddress, BluetoothDevice.ADDRESS_TYPE_RANDOM);

        byte[] scanRecordWithBaseData =
                new byte[] {
                    (byte) 0x02,
                    (byte) 0x01,
                    (byte) 0x1a, // advertising flags
                    (byte) 0x05,
                    (byte) 0x02,
                    (byte) 0x51,
                    (byte) 0x18,
                    (byte) 0x0a,
                    (byte) 0x11, // 16 bit service uuids
                    (byte) 0x04,
                    (byte) 0x09,
                    (byte) 0x50,
                    (byte) 0x65,
                    (byte) 0x64, // name
                    (byte) 0x02,
                    (byte) 0x0A,
                    (byte) 0xec, // tx power level
                    (byte) 0x19,
                    (byte) 0x16,
                    (byte) 0x51,
                    (byte) 0x18, // service data (base data with 18 bytes)
                    // LEVEL 1
                    (byte) 0x01,
                    (byte) 0x02,
                    (byte) 0x03, // presentationDelay
                    (byte) 0x01, // numSubGroups
                    // LEVEL 2
                    (byte) 0x01, // numSubGroups
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00,
                    (byte) 0x00, // UNKNOWN_CODEC
                    (byte) 0x02, // codecConfigLength
                    (byte) 0x01,
                    (byte) 'A', // codecConfigInfo
                    (byte) 0x03, // metaDataLength
                    (byte) 0x06,
                    (byte) 0x07,
                    (byte) 0x08, // metaData
                    // LEVEL 3
                    (byte) 0x04, // index
                    (byte) 0x03, // codecConfigLength
                    (byte) 0x02,
                    (byte) 'B',
                    (byte) 'C', // codecConfigInfo
                    (byte) 0x05,
                    (byte) 0xff,
                    (byte) 0xe0,
                    (byte) 0x00,
                    (byte) 0x02,
                    (byte) 0x15, // manufacturer specific data
                    (byte) 0x03,
                    (byte) 0x50,
                    (byte) 0x01,
                    (byte) 0x02, // an unknown data type won't cause trouble
                };

        ScanRecord record = ScanRecord.parseFromBytes(scanRecordWithBaseData);
        ScanResult scanResult =
                new ScanResult(
                        mAdapter.getRemoteLeDevice(
                                "00:11:22:33:44:55", BluetoothDevice.ADDRESS_TYPE_RANDOM),
                        0,
                        0,
                        0,
                        0,
                        0,
                        testRssi,
                        0,
                        record,
                        0);
        BaseData data =
                BaseData.parseBaseData(record.getServiceData(BassConstants.BASIC_AUDIO_UUID));

        when(mBassClientService.getDeviceForSyncHandle(syncHandle)).thenReturn(testDevice);
        PeriodicAdvertisementResult paResult = Mockito.mock(PeriodicAdvertisementResult.class);
        when(mBassClientService.getPeriodicAdvertisementResult(any(), anyInt()))
                .thenReturn(paResult);
        when(paResult.isNotified()).thenReturn(false);
        when(mBassClientService.getBase(anyInt())).thenReturn(data);
        when(mBassClientService.getCachedBroadcast(anyInt())).thenReturn(scanResult);
        when(mBassClientService.getCallbacks()).thenReturn(callbacks);

        cb.onBigInfoAdvertisingReport(syncHandle, true);
        ArgumentCaptor<BluetoothLeBroadcastMetadata> metaData =
                ArgumentCaptor.forClass(BluetoothLeBroadcastMetadata.class);
        verify(callbacks).notifySourceFound(metaData.capture());

        Assert.assertEquals(testRssi, metaData.getValue().getRssi());
    }

    private void initToConnectingState() {
        allowConnection(true);
        allowConnectGatt(true);
+3 −0
Original line number Diff line number Diff line
@@ -616,6 +616,7 @@ package android.bluetooth {
    method public int getPaSyncInterval();
    method @IntRange(from=0, to=16777215) public int getPresentationDelayMicros();
    method @Nullable public android.bluetooth.BluetoothLeAudioContentMetadata getPublicBroadcastMetadata();
    method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") @IntRange(from=0xffffff81, to=127) public int getRssi();
    method public int getSourceAddressType();
    method public int getSourceAdvertisingSid();
    method @NonNull public android.bluetooth.BluetoothDevice getSourceDevice();
@@ -628,6 +629,7 @@ package android.bluetooth {
    field public static final int AUDIO_CONFIG_QUALITY_STANDARD = 1; // 0x1
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothLeBroadcastMetadata> CREATOR;
    field public static final int PA_SYNC_INTERVAL_UNKNOWN = 65535; // 0xffff
    field @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") public static final int RSSI_UNKNOWN = 127; // 0x7f
  }

  public static final class BluetoothLeBroadcastMetadata.Builder {
@@ -645,6 +647,7 @@ package android.bluetooth {
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPresentationDelayMicros(@IntRange(from=0, to=16777215) int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPublicBroadcast(boolean);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPublicBroadcastMetadata(@Nullable android.bluetooth.BluetoothLeAudioContentMetadata);
    method @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status") @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setRssi(@IntRange(from=0xffffff81, to=127) int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceAdvertisingSid(int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceDevice(@NonNull android.bluetooth.BluetoothDevice, int);
  }
+138 −54
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.bluetooth;

import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -58,6 +59,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
    private final byte[] mBroadcastCode;
    private final BluetoothLeAudioContentMetadata mPublicBroadcastMetadata;
    private final @AudioConfigQuality int mAudioConfigQuality;
    private final int mRssi;

    /**
     * Audio configuration quality for this Broadcast Group.
@@ -117,11 +119,19 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
    // Sub group info numSubGroup = mSubGroups.length
    private final List<BluetoothLeBroadcastSubgroup> mSubgroups;

    private BluetoothLeBroadcastMetadata(int sourceAddressType,
            BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId,
            int paSyncInterval, boolean isEncrypted, boolean isPublicBroadcast,
            String broadcastName, byte[] broadcastCode, int presentationDelay,
    private BluetoothLeBroadcastMetadata(
            int sourceAddressType,
            BluetoothDevice sourceDevice,
            int sourceAdvertisingSid,
            int broadcastId,
            int paSyncInterval,
            boolean isEncrypted,
            boolean isPublicBroadcast,
            String broadcastName,
            byte[] broadcastCode,
            int presentationDelay,
            @AudioConfigQuality int audioConfigQuality,
            int rssi,
            BluetoothLeAudioContentMetadata publicBroadcastMetadata,
            List<BluetoothLeBroadcastSubgroup> subgroups) {
        mSourceAddressType = sourceAddressType;
@@ -135,6 +145,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
        mBroadcastCode = broadcastCode;
        mPresentationDelayMicros = presentationDelay;
        mAudioConfigQuality = audioConfigQuality;
        mRssi = rssi;
        mPublicBroadcastMetadata = publicBroadcastMetadata;
        mSubgroups = subgroups;
    }
@@ -156,16 +167,27 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
                && Arrays.equals(mBroadcastCode, other.getBroadcastCode())
                && mPresentationDelayMicros == other.getPresentationDelayMicros()
                && mAudioConfigQuality == other.getAudioConfigQuality()
                && mRssi == other.getRssi()
                && Objects.equals(mPublicBroadcastMetadata, other.getPublicBroadcastMetadata())
                && mSubgroups.equals(other.getSubgroups());
    }

    @Override
    public int hashCode() {
        return Objects.hash(mSourceAddressType, mSourceDevice, mSourceAdvertisingSid,
                mBroadcastId, mPaSyncInterval, mIsEncrypted, mIsPublicBroadcast,
                mBroadcastName, Arrays.hashCode(mBroadcastCode),
                mPresentationDelayMicros, mAudioConfigQuality, mPublicBroadcastMetadata,
        return Objects.hash(
                mSourceAddressType,
                mSourceDevice,
                mSourceAdvertisingSid,
                mBroadcastId,
                mPaSyncInterval,
                mIsEncrypted,
                mIsPublicBroadcast,
                mBroadcastName,
                Arrays.hashCode(mBroadcastCode),
                mPresentationDelayMicros,
                mAudioConfigQuality,
                mRssi,
                mPublicBroadcastMetadata,
                mSubgroups);
    }

@@ -314,6 +336,31 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
        return mAudioConfigQuality;
    }

    /**
     * Indicated that rssi value is unknown.
     *
     * @hide
     */
    @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status")
    @SystemApi
    public static final int RSSI_UNKNOWN = 0x7F;

    /**
     * Get the Received Signal Strength Indication (RSSI) value of this Broadcast Source.
     *
     * <p>The valid RSSI range is [-127, 126] and as defined in Volume 4, Part E, Section 7.7.65.13
     * of Bluetooth Core Specification, Version 5.3, value of 0x7F(127) means that the RSSI is not
     * available.
     *
     * @return the RSSI {@link #RSSI_UNKNOWN} if unknown
     * @hide
     */
    @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status")
    @SystemApi
    public @IntRange(from = -127, to = 127) int getRssi() {
        return mRssi;
    }

    /**
     * Get public broadcast metadata for this Broadcast Group.
     *
@@ -378,6 +425,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
        out.writeString(mBroadcastName);
        out.writeInt(mAudioConfigQuality);
        out.writeTypedObject(mPublicBroadcastMetadata, 0);
        out.writeInt(mRssi);
    }

    /**
@@ -385,9 +433,9 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
     *
     * @hide
     */
    @SystemApi
    @NonNull
    public static final Creator<BluetoothLeBroadcastMetadata> CREATOR = new Creator<>() {
    @SystemApi @NonNull
    public static final Creator<BluetoothLeBroadcastMetadata> CREATOR =
            new Creator<>() {
                public @NonNull BluetoothLeBroadcastMetadata createFromParcel(@NonNull Parcel in) {
                    Builder builder = new Builder();
                    final int sourceAddressType = in.readInt();
@@ -421,6 +469,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
                    builder.setAudioConfigQuality(in.readInt());
                    builder.setPublicBroadcastMetadata(
                            in.readTypedObject(BluetoothLeAudioContentMetadata.CREATOR));
                    builder.setRssi(in.readInt());
                    return builder.build();
                }

@@ -449,6 +498,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
        private byte[] mBroadcastCode = null;
        private int mPresentationDelayMicros = UNKNOWN_VALUE_PLACEHOLDER;
        private @AudioConfigQuality int mAudioConfigQuality = AUDIO_CONFIG_QUALITY_NONE;
        private int mRssi = RSSI_UNKNOWN;
        private BluetoothLeAudioContentMetadata mPublicBroadcastMetadata = null;
        private List<BluetoothLeBroadcastSubgroup> mSubgroups = new ArrayList<>();

@@ -479,6 +529,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
            mBroadcastCode = original.getBroadcastCode();
            mPresentationDelayMicros = original.getPresentationDelayMicros();
            mAudioConfigQuality = original.getAudioConfigQuality();
            mRssi = original.getRssi();
            mPublicBroadcastMetadata = original.getPublicBroadcastMetadata();
            mSubgroups = original.getSubgroups();
        }
@@ -664,6 +715,29 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
            return this;
        }

        /**
         * Set the Received Signal Strength Indication (RSSI) value for this Broadcast metadata.
         *
         * <p>The valid RSSI range is [-127, 126] and as defined in Volume 4, Part E, Section
         * 7.7.65.13 of Bluetooth Core Specification, Version 5.3, value of 0x7F(127) means that the
         * RSSI is not available.
         *
         * @param rssi the RSSI
         * @return this builder
         * @throws IllegalArgumentException if rssi is not in the range [-127, 127].
         * @hide
         */
        @FlaggedApi("com.android.bluetooth.flags.leaudio_broadcast_monitor_source_sync_status")
        @SystemApi
        @NonNull
        public Builder setRssi(@IntRange(from = -127, to = 127) int rssi) {
            if (rssi < -127 || rssi > 127) {
                throw new IllegalArgumentException("illegal rssi " + rssi);
            }
            mRssi = rssi;
            return this;
        }

        /**
         * Set public broadcast metadata for this Broadcast Group.
         * PBS should include the Program_Info length-type-value (LTV) structure metadata
@@ -731,11 +805,21 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
            if (mSubgroups.isEmpty()) {
                throw new IllegalArgumentException("Must contain at least one subgroup");
            }
            return new BluetoothLeBroadcastMetadata(mSourceAddressType, mSourceDevice,
                    mSourceAdvertisingSid, mBroadcastId, mPaSyncInterval, mIsEncrypted,
                    mIsPublicBroadcast, mBroadcastName, mBroadcastCode,
                    mPresentationDelayMicros, mAudioConfigQuality,
                    mPublicBroadcastMetadata, mSubgroups);
            return new BluetoothLeBroadcastMetadata(
                    mSourceAddressType,
                    mSourceDevice,
                    mSourceAdvertisingSid,
                    mBroadcastId,
                    mPaSyncInterval,
                    mIsEncrypted,
                    mIsPublicBroadcast,
                    mBroadcastName,
                    mBroadcastCode,
                    mPresentationDelayMicros,
                    mAudioConfigQuality,
                    mRssi,
                    mPublicBroadcastMetadata,
                    mSubgroups);
        }
    }
}
Loading