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

Commit ee12f766 authored by Jack He's avatar Jack He
Browse files

Broadcast: Strict argument checking for data structures

* Require @Nonnull elements to be not null when building or
  constructing objects
* Enfore argument range

Bug: 218683032
Test: make, cts
Tag: #feature
Change-Id: I53a6657323c9b93c971c9f43994a4a7c6b88e40d
parent b8918397
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -490,7 +490,7 @@ package android.bluetooth {
    method @IntRange(from=0, to=16777215) public int getPresentationDelayMicros();
    method public int getSourceAddressType();
    method public int getSourceAdvertisingSid();
    method @Nullable public android.bluetooth.BluetoothDevice getSourceDevice();
    method @NonNull public android.bluetooth.BluetoothDevice getSourceDevice();
    method @NonNull public java.util.List<android.bluetooth.BluetoothLeBroadcastSubgroup> getSubgroups();
    method public boolean isEncrypted();
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothLeBroadcastMetadata> CREATOR;
@@ -509,7 +509,7 @@ package android.bluetooth {
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPaSyncInterval(int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setPresentationDelayMicros(@IntRange(from=0, to=16777215) int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceAdvertisingSid(int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceDevice(@Nullable android.bluetooth.BluetoothDevice, int);
    method @NonNull public android.bluetooth.BluetoothLeBroadcastMetadata.Builder setSourceDevice(@NonNull android.bluetooth.BluetoothDevice, int);
  }

  public final class BluetoothLeBroadcastReceiveState implements android.os.Parcelable {
+16 −3
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * This class contains the Broadcast Isochronous Channel level information as defined in the BASE
 * structure of the Basic Audio Profile.
@@ -168,11 +170,17 @@ public final class BluetoothLeBroadcastChannel implements Parcelable {
        /**
         * Set the Broadcast Isochronous Channel index of this Broadcast Channel.
         *
         * @return Broadcast Isochronous Channel index
         * @param channelIndex Broadcast Isochronous Channel index
         * @throws IllegalArgumentException if the input argument is not valid
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setChannelIndex(int channelIndex) {
            if (channelIndex == UNKNOWN_VALUE_PLACEHOLDER) {
                throw new IllegalArgumentException("channelIndex cannot be "
                        + UNKNOWN_VALUE_PLACEHOLDER);
            }
            mChannelIndex = channelIndex;
            return this;
        }
@@ -181,12 +189,14 @@ public final class BluetoothLeBroadcastChannel implements Parcelable {
         * Set the codec specific configuration for this Broadcast Channel.
         *
         * @param codecMetadata codec specific configuration for this Broadcast Channel
         * @throws NullPointerException if codecMetadata is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setCodecMetadata(
                @NonNull BluetoothLeAudioCodecConfigMetadata codecMetadata) {
            Objects.requireNonNull(codecMetadata, "codecMetadata cannot be null");
            mCodecMetadata = codecMetadata;
            return this;
        }
@@ -195,13 +205,16 @@ public final class BluetoothLeBroadcastChannel implements Parcelable {
         * Build {@link BluetoothLeBroadcastChannel}.
         *
         * @return constructed {@link BluetoothLeBroadcastChannel}
         * @throws NullPointerException if {@link NonNull} items are null
         * @throws IllegalArgumentException if the object cannot be built
         * @hide
         */
        @SystemApi
        public @NonNull BluetoothLeBroadcastChannel build() {
            if (mCodecMetadata == null) {
                throw new IllegalArgumentException("codec metadata cannot be null");
            Objects.requireNonNull(mCodecMetadata, "codec metadata cannot be null");
            if (mChannelIndex == UNKNOWN_VALUE_PLACEHOLDER) {
                throw new IllegalArgumentException("mChannelIndex cannot be "
                        + UNKNOWN_VALUE_PLACEHOLDER);
            }
            return new BluetoothLeBroadcastChannel(mIsSelected, mChannelIndex, mCodecMetadata);
        }
+31 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * This class represents a Broadcast Source group and the associated information that is needed
@@ -97,7 +98,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
     * @hide
     */
    @SystemApi
    public @Nullable BluetoothDevice getSourceDevice() {
    public @NonNull BluetoothDevice getSourceDevice() {
        return mSourceDevice;
    }

@@ -300,6 +301,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {

        /**
         * Create an empty builder.
         *
         * @hide
         */
        @SystemApi
@@ -336,14 +338,26 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
         *
         * @param sourceDevice source advertiser address
         * @param sourceAddressType source advertiser address type
         * @throws IllegalArgumentException if sourceAddressType is invalid
         * @throws NullPointerException if sourceDevice is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setSourceDevice(@Nullable BluetoothDevice sourceDevice,
        public @NonNull Builder setSourceDevice(@NonNull BluetoothDevice sourceDevice,
                @BluetoothDevice.AddressType int sourceAddressType) {
            mSourceDevice = sourceDevice;
            if (sourceAddressType == BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
                throw new IllegalArgumentException(
                        "sourceAddressType cannot be ADDRESS_TYPE_UNKNOWN");
            }
            if (sourceAddressType != BluetoothDevice.ADDRESS_TYPE_RANDOM
                    && sourceAddressType != BluetoothDevice.ADDRESS_TYPE_PUBLIC) {
                throw new IllegalArgumentException("sourceAddressType " + sourceAddressType
                        + " is invalid");
            }
            Objects.requireNonNull(sourceDevice, "sourceDevice cannot be null");
            mSourceAddressType = sourceAddressType;
            mSourceDevice = sourceDevice;
            return this;
        }

@@ -433,12 +447,18 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
         *
         * @param presentationDelayMicros presentation delay of this Broadcast Source in
         *                                microseconds
         * @throws IllegalArgumentException if presentationDelayMicros does not fall in
         *                                  [0, 0xFFFFFF]
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setPresentationDelayMicros(
                @IntRange(from = 0, to = 0xFFFFFF) int presentationDelayMicros) {
            if (presentationDelayMicros < 0 || presentationDelayMicros >= 0xFFFFFF) {
                throw new IllegalArgumentException("presentationDelayMicros "
                        + presentationDelayMicros + " does not fall in [0, 0xFFFFFF]");
            }
            mPresentationDelayMicros = presentationDelayMicros;
            return this;
        }
@@ -447,11 +467,13 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
         * Add a subgroup to this broadcast source.
         *
         * @param subgroup {@link BluetoothLeBroadcastSubgroup} that contains a subgroup's metadata
         * @throws NullPointerException if subgroup is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder addSubgroup(@NonNull BluetoothLeBroadcastSubgroup subgroup) {
            Objects.requireNonNull(subgroup, "subgroup cannot be null");
            mSubgroups.add(subgroup);
            return this;
        }
@@ -474,6 +496,7 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
         *
         * @return {@link BluetoothLeBroadcastMetadata}
         * @throws IllegalArgumentException if the object cannot be built
         * @throws NullPointerException if {@link NonNull} items are null
         * @hide
         */
        @SystemApi
@@ -481,9 +504,12 @@ public final class BluetoothLeBroadcastMetadata implements Parcelable {
            if (mSourceAddressType == BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
                throw new IllegalArgumentException("SourceAddressTyp cannot be unknown");
            }
            if (mSourceDevice == null) {
                throw new IllegalArgumentException("SourceDevice cannot be null");
            if (mSourceAddressType != BluetoothDevice.ADDRESS_TYPE_RANDOM
                    && mSourceAddressType != BluetoothDevice.ADDRESS_TYPE_PUBLIC) {
                throw new IllegalArgumentException("sourceAddressType " + mSourceAddressType
                        + " is invalid");
            }
            Objects.requireNonNull(mSourceDevice, "mSourceDevice cannot be null");
            if (mSubgroups.isEmpty()) {
                throw new IllegalArgumentException("Must contain at least one subgroup");
            }
+52 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * The {@link BluetoothLeBroadcastReceiveState} is used by the BASS server to expose information
@@ -187,13 +188,59 @@ public final class BluetoothLeBroadcastReceiveState implements Parcelable {
    /**
     * Constructor to create a read-only {@link BluetoothLeBroadcastReceiveState} instance.
     *
     * @throws NullPointerException if sourceDevice, bisSyncState, or subgroupMetadata is null
     * @throws IllegalArgumentException if sourceID is not [0, 0xFF] or if sourceAddressType
     *      is invalid or if bisSyncState.size() != numSubgroups or if subgroupMetadata.size() !=
     *      numSubgroups or if paSyncState or bigEncryptionState is not recognized bye IntDef
     * @hide
     */
    public BluetoothLeBroadcastReceiveState(int sourceId, int sourceAddressType,
            BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId,
            int paSyncState, int bigEncryptionState, byte[] badCode, int numSubgroups,
            List<Long> bisSyncState,
            List<BluetoothLeAudioContentMetadata> subgroupMetadata) {
    public BluetoothLeBroadcastReceiveState(@IntRange(from = 0x00, to = 0xFF) int sourceId,
            @BluetoothDevice.AddressType int sourceAddressType,
            @NonNull BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId,
            @PaSyncState int paSyncState, @BigEncryptionState int bigEncryptionState,
            byte[] badCode, @IntRange(from = 0x00) int numSubgroups,
            @NonNull List<Long> bisSyncState,
            @NonNull List<BluetoothLeAudioContentMetadata> subgroupMetadata) {
        if (sourceId < 0x00 || sourceId > 0xFF) {
            throw new IllegalArgumentException("sourceId " + sourceId
                    + " does not fall between 0x00 and 0xFF");
        }
        Objects.requireNonNull(sourceDevice, "sourceDevice cannot be null");
        if (sourceAddressType == BluetoothDevice.ADDRESS_TYPE_UNKNOWN) {
            throw new IllegalArgumentException("sourceAddressType cannot be ADDRESS_TYPE_UNKNOWN");
        }
        if (sourceAddressType != BluetoothDevice.ADDRESS_TYPE_RANDOM
                && sourceAddressType != BluetoothDevice.ADDRESS_TYPE_PUBLIC) {
            throw new IllegalArgumentException("sourceAddressType " + sourceAddressType
                    + " is invalid");
        }
        Objects.requireNonNull(bisSyncState, "bisSyncState cannot be null");
        if (bisSyncState.size() != numSubgroups) {
            throw new IllegalArgumentException("bisSyncState.size() " + bisSyncState.size()
                    + " must be equal to numSubgroups " + numSubgroups);
        }
        Objects.requireNonNull(subgroupMetadata, "subgroupMetadata cannot be null");
        if (subgroupMetadata.size() != numSubgroups) {
            throw new IllegalArgumentException("subgroupMetadata.size()  "
                    + subgroupMetadata.size() + " must be equal to numSubgroups " + numSubgroups);
        }
        if (paSyncState != PA_SYNC_STATE_IDLE && paSyncState != PA_SYNC_STATE_SYNCINFO_REQUEST
                && paSyncState != PA_SYNC_STATE_FAILED_TO_SYNCHRONIZE
                && paSyncState != PA_SYNC_STATE_NO_PAST && paSyncState != PA_SYNC_STATE_INVALID) {
            throw new IllegalArgumentException("unrecognized paSyncState " + paSyncState);
        }
        if (bigEncryptionState != BIG_ENCRYPTION_STATE_NOT_ENCRYPTED
                && bigEncryptionState != BIG_ENCRYPTION_STATE_CODE_REQUIRED
                && bigEncryptionState != BIG_ENCRYPTION_STATE_DECRYPTING
                && bigEncryptionState != BIG_ENCRYPTION_STATE_BAD_CODE
                && bigEncryptionState != BIG_ENCRYPTION_STATE_INVALID) {
            throw new IllegalArgumentException("unrecognized bigEncryptionState "
                    + bigEncryptionState);
        }
        if (badCode != null && badCode.length != 16) {
            throw new IllegalArgumentException("badCode must be 16 bytes long of null, but is "
                    + badCode.length + " + bytes long");
        }
        mSourceId = sourceId;
        mSourceAddressType = sourceAddressType;
        mSourceDevice = sourceDevice;
+11 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * This class contains the subgroup level information as defined in the BASE structure of Basic
@@ -178,6 +179,7 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {

        /**
         * Create an empty constructor.
         *
         * @hide
         */
        @SystemApi
@@ -197,7 +199,6 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
            mChannels = original.getChannels();
        }


        /**
         * Set the codec ID field as defined by the Basic Audio Profile.
         *
@@ -222,12 +223,14 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
         * Set codec specific config metadata for this subgroup.
         *
         * @param codecSpecificConfig codec specific config metadata for this subgroup
         * @throws {@link NullPointerException} if codecSpecificConfig is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setCodecSpecificConfig(
                @NonNull BluetoothLeAudioCodecConfigMetadata codecSpecificConfig) {
            Objects.requireNonNull(codecSpecificConfig, "codecSpecificConfig cannot be null");
            mCodecSpecificConfig = codecSpecificConfig;
            return this;
        }
@@ -236,12 +239,14 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
         * Set content metadata for this Broadcast Source subgroup.
         *
         * @param contentMetadata content metadata for this Broadcast Source subgroup
         * @throws NullPointerException if contentMetadata is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder setContentMetadata(
                @NonNull BluetoothLeAudioContentMetadata contentMetadata) {
            Objects.requireNonNull(contentMetadata, "contentMetadata cannot be null");
            mContentMetadata = contentMetadata;
            return this;
        }
@@ -254,11 +259,13 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
         * A Broadcast subgroup should contain at least 1 Broadcast Channel
         *
         * @param channel  a Broadcast Channel to be added to this Broadcast subgroup
         * @throws NullPointerException if channel is null
         * @return this builder
         * @hide
         */
        @SystemApi
        public @NonNull Builder addChannel(@NonNull BluetoothLeBroadcastChannel channel) {
            Objects.requireNonNull(channel, "channel cannot be null");
            mChannels.add(channel);
            return this;
        }
@@ -280,17 +287,14 @@ public final class BluetoothLeBroadcastSubgroup implements Parcelable {
         * Build {@link BluetoothLeBroadcastSubgroup}.
         *
         * @return constructed {@link BluetoothLeBroadcastSubgroup}
         * @throws NullPointerException if {@link NonNull} items are null
         * @throws IllegalArgumentException if the object cannot be built
         * @hide
         */
        @SystemApi
        public @NonNull BluetoothLeBroadcastSubgroup build() {
            if (mCodecSpecificConfig == null) {
                throw new IllegalArgumentException("CodecSpecificConfig is null");
            }
            if (mContentMetadata == null) {
                throw new IllegalArgumentException("ContentMetadata is null");
            }
            Objects.requireNonNull(mCodecSpecificConfig, "CodecSpecificConfig is null");
            Objects.requireNonNull(mContentMetadata, "ContentMetadata is null");
            if (mChannels.isEmpty()) {
                throw new IllegalArgumentException("Must have at least one channel");
            }