summaryrefslogtreecommitdiff
path: root/framework/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'framework/java/android')
-rw-r--r--framework/java/android/bluetooth/BluetoothAdapter.java35
-rw-r--r--framework/java/android/bluetooth/BluetoothCodecConfig.java497
-rw-r--r--framework/java/android/bluetooth/BluetoothCodecStatus.java111
-rw-r--r--framework/java/android/bluetooth/BluetoothGattServer.java78
-rw-r--r--framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java129
-rw-r--r--framework/java/android/bluetooth/BluetoothLeBroadcast.java287
-rw-r--r--framework/java/android/bluetooth/BluetoothProfile.java11
-rw-r--r--framework/java/android/bluetooth/BluetoothSocket.java3
-rw-r--r--framework/java/android/bluetooth/BluetoothStatusCodes.java60
9 files changed, 923 insertions, 288 deletions
diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java
index cf00cbd584..2c875fee10 100644
--- a/framework/java/android/bluetooth/BluetoothAdapter.java
+++ b/framework/java/android/bluetooth/BluetoothAdapter.java
@@ -51,7 +51,6 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
-import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
@@ -59,7 +58,6 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.SynchronousResultReceiver;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;
@@ -82,7 +80,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -2424,38 +2421,6 @@ public final class BluetoothAdapter {
}
/**
- * Return the record of {@link BluetoothActivityEnergyInfo} object that
- * has the activity and energy info. This can be used to ascertain what
- * the controller has been up to, since the last sample.
- *
- * @param updateType Type of info, cached vs refreshed.
- * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
- * unsupported
- * @hide
- * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
- * instead.
- */
- @Deprecated
- @RequiresBluetoothConnectPermission
- @RequiresPermission(allOf = {
- android.Manifest.permission.BLUETOOTH_CONNECT,
- android.Manifest.permission.BLUETOOTH_PRIVILEGED,
- })
- public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
- SynchronousResultReceiver receiver = new SynchronousResultReceiver();
- requestControllerActivityEnergyInfo(receiver);
- try {
- SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
- if (result.bundle != null) {
- return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
- }
- } catch (TimeoutException e) {
- Log.e(TAG, "getControllerActivityEnergyInfo timed out");
- }
- return null;
- }
-
- /**
* Request the record of {@link BluetoothActivityEnergyInfo} object that
* has the activity and energy info. This can be used to ascertain what
* the controller has been up to, since the last sample.
diff --git a/framework/java/android/bluetooth/BluetoothCodecConfig.java b/framework/java/android/bluetooth/BluetoothCodecConfig.java
index 1d0bf97c34..9a4151adff 100644
--- a/framework/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/framework/java/android/bluetooth/BluetoothCodecConfig.java
@@ -29,16 +29,14 @@ import java.util.Objects;
/**
* Represents the codec configuration for a Bluetooth A2DP source device.
+ * <p>Contains the source codec type, the codec priority, the codec sample
+ * rate, the codec bits per sample, and the codec channel mode.
+ * <p>The source codec type values are the same as those supported by the
+ * device hardware.
*
* {@see BluetoothA2dp}
- *
- * {@hide}
*/
public final class BluetoothCodecConfig implements Parcelable {
- // Add an entry for each source codec here.
- // NOTE: The values should be same as those listed in the following file:
- // hardware/libhardware/include/hardware/bt_av.h
-
/** @hide */
@IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
SOURCE_CODEC_TYPE_SBC,
@@ -46,33 +44,49 @@ public final class BluetoothCodecConfig implements Parcelable {
SOURCE_CODEC_TYPE_APTX,
SOURCE_CODEC_TYPE_APTX_HD,
SOURCE_CODEC_TYPE_LDAC,
- SOURCE_CODEC_TYPE_MAX,
SOURCE_CODEC_TYPE_INVALID
})
@Retention(RetentionPolicy.SOURCE)
public @interface SourceCodecType {}
- @UnsupportedAppUsage
+ /**
+ * Source codec type SBC. This is the mandatory source codec
+ * type.
+ */
public static final int SOURCE_CODEC_TYPE_SBC = 0;
- @UnsupportedAppUsage
+ /**
+ * Source codec type AAC.
+ */
public static final int SOURCE_CODEC_TYPE_AAC = 1;
- @UnsupportedAppUsage
+ /**
+ * Source codec type APTX.
+ */
public static final int SOURCE_CODEC_TYPE_APTX = 2;
- @UnsupportedAppUsage
+ /**
+ * Source codec type APTX HD.
+ */
public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
- @UnsupportedAppUsage
+ /**
+ * Source codec type LDAC.
+ */
public static final int SOURCE_CODEC_TYPE_LDAC = 4;
- @UnsupportedAppUsage
- public static final int SOURCE_CODEC_TYPE_MAX = 5;
-
- @UnsupportedAppUsage
+ /**
+ * Source codec type invalid. This is the default value used for codec
+ * type.
+ */
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+ /**
+ * Represents the count of valid source codec types. Can be accessed via
+ * {@link #getMaxCodecType}.
+ */
+ private static final int SOURCE_CODEC_TYPE_MAX = 5;
+
/** @hide */
@IntDef(prefix = "CODEC_PRIORITY_", value = {
CODEC_PRIORITY_DISABLED,
@@ -82,16 +96,24 @@ public final class BluetoothCodecConfig implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface CodecPriority {}
- @UnsupportedAppUsage
+ /**
+ * Codec priority disabled.
+ * Used to indicate that this codec is disabled and should not be used.
+ */
public static final int CODEC_PRIORITY_DISABLED = -1;
- @UnsupportedAppUsage
+ /**
+ * Codec priority default.
+ * Default value used for codec priority.
+ */
public static final int CODEC_PRIORITY_DEFAULT = 0;
- @UnsupportedAppUsage
+ /**
+ * Codec priority highest.
+ * Used to indicate the highest priority a codec can have.
+ */
public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
-
/** @hide */
@IntDef(prefix = "SAMPLE_RATE_", value = {
SAMPLE_RATE_NONE,
@@ -105,28 +127,42 @@ public final class BluetoothCodecConfig implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface SampleRate {}
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 0 Hz. Default value used for
+ * codec sample rate.
+ */
public static final int SAMPLE_RATE_NONE = 0;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 44100 Hz.
+ */
public static final int SAMPLE_RATE_44100 = 0x1 << 0;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 48000 Hz.
+ */
public static final int SAMPLE_RATE_48000 = 0x1 << 1;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 88200 Hz.
+ */
public static final int SAMPLE_RATE_88200 = 0x1 << 2;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 96000 Hz.
+ */
public static final int SAMPLE_RATE_96000 = 0x1 << 3;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 176400 Hz.
+ */
public static final int SAMPLE_RATE_176400 = 0x1 << 4;
- @UnsupportedAppUsage
+ /**
+ * Codec sample rate 192000 Hz.
+ */
public static final int SAMPLE_RATE_192000 = 0x1 << 5;
-
/** @hide */
@IntDef(prefix = "BITS_PER_SAMPLE_", value = {
BITS_PER_SAMPLE_NONE,
@@ -137,19 +173,27 @@ public final class BluetoothCodecConfig implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface BitsPerSample {}
- @UnsupportedAppUsage
+ /**
+ * Codec bits per sample 0. Default value of the codec
+ * bits per sample.
+ */
public static final int BITS_PER_SAMPLE_NONE = 0;
- @UnsupportedAppUsage
+ /**
+ * Codec bits per sample 16.
+ */
public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
- @UnsupportedAppUsage
+ /**
+ * Codec bits per sample 24.
+ */
public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
- @UnsupportedAppUsage
+ /**
+ * Codec bits per sample 32.
+ */
public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
-
/** @hide */
@IntDef(prefix = "CHANNEL_MODE_", value = {
CHANNEL_MODE_NONE,
@@ -159,13 +203,20 @@ public final class BluetoothCodecConfig implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface ChannelMode {}
- @UnsupportedAppUsage
+ /**
+ * Codec channel mode NONE. Default value of the
+ * codec channel mode.
+ */
public static final int CHANNEL_MODE_NONE = 0;
- @UnsupportedAppUsage
+ /**
+ * Codec channel mode MONO.
+ */
public static final int CHANNEL_MODE_MONO = 0x1 << 0;
- @UnsupportedAppUsage
+ /**
+ * Codec channel mode STEREO.
+ */
public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
private final @SourceCodecType int mCodecType;
@@ -178,6 +229,21 @@ public final class BluetoothCodecConfig implements Parcelable {
private final long mCodecSpecific3;
private final long mCodecSpecific4;
+ /**
+ * Creates a new BluetoothCodecConfig.
+ *
+ * @param codecType the source codec type
+ * @param codecPriority the priority of this codec
+ * @param sampleRate the codec sample rate
+ * @param bitsPerSample the bits per sample of this codec
+ * @param channelMode the channel mode of this codec
+ * @param codecSpecific1 the specific value 1
+ * @param codecSpecific2 the specific value 2
+ * @param codecSpecific3 the specific value 3
+ * @param codecSpecific4 the specific value 4
+ * values to 0.
+ * @hide
+ */
@UnsupportedAppUsage
public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
@SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
@@ -195,17 +261,34 @@ public final class BluetoothCodecConfig implements Parcelable {
mCodecSpecific4 = codecSpecific4;
}
- @UnsupportedAppUsage
+ /**
+ * Creates a new BluetoothCodecConfig.
+ * <p> By default, the codec priority will be set
+ * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
+ * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
+ * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
+ * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
+ * values to 0.
+ *
+ * @param codecType the source codec type
+ */
public BluetoothCodecConfig(@SourceCodecType int codecType) {
- mCodecType = codecType;
- mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
- mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
- mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
- mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
- mCodecSpecific1 = 0;
- mCodecSpecific2 = 0;
- mCodecSpecific3 = 0;
- mCodecSpecific4 = 0;
+ this(codecType, BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+ BluetoothCodecConfig.SAMPLE_RATE_NONE,
+ BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
+ BluetoothCodecConfig.CHANNEL_MODE_NONE, 0, 0, 0, 0);
+ }
+
+ private BluetoothCodecConfig(Parcel in) {
+ mCodecType = in.readInt();
+ mCodecPriority = in.readInt();
+ mSampleRate = in.readInt();
+ mBitsPerSample = in.readInt();
+ mChannelMode = in.readInt();
+ mCodecSpecific1 = in.readLong();
+ mCodecSpecific2 = in.readLong();
+ mCodecSpecific3 = in.readLong();
+ mCodecSpecific4 = in.readLong();
}
@Override
@@ -226,10 +309,8 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Returns a hash based on the config values
- *
- * @return a hash based on the config values
- * @hide
+ * Returns a hash representation of this BluetoothCodecConfig
+ * based on all the config values.
*/
@Override
public int hashCode() {
@@ -239,32 +320,24 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Checks whether the object contains valid codec configuration.
- *
- * @return true if the object contains valid codec configuration, otherwise false.
- * @hide
- */
- public boolean isValid() {
- return (mSampleRate != SAMPLE_RATE_NONE)
- && (mBitsPerSample != BITS_PER_SAMPLE_NONE)
- && (mChannelMode != CHANNEL_MODE_NONE);
- }
-
- /**
* Adds capability string to an existing string.
*
- * @param prevStr the previous string with the capabilities. Can be a null pointer.
- * @param capStr the capability string to append to prevStr argument.
- * @return the result string in the form "prevStr|capStr".
+ * @param prevStr the previous string with the capabilities. Can be a {@code null} pointer
+ * @param capStr the capability string to append to prevStr argument
+ * @return the result string in the form "prevStr|capStr"
*/
- private static String appendCapabilityToString(String prevStr,
- String capStr) {
+ private static String appendCapabilityToString(@Nullable String prevStr,
+ @NonNull String capStr) {
if (prevStr == null) {
return capStr;
}
return prevStr + "|" + capStr;
}
+ /**
+ * Returns a {@link String} that describes each BluetoothCodecConfig parameter
+ * current value.
+ */
@Override
public String toString() {
String sampleRateStr = null;
@@ -331,8 +404,6 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Always returns 0
- *
* @return 0
* @hide
*/
@@ -344,20 +415,7 @@ public final class BluetoothCodecConfig implements Parcelable {
public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecConfig> CREATOR =
new Parcelable.Creator<BluetoothCodecConfig>() {
public BluetoothCodecConfig createFromParcel(Parcel in) {
- final int codecType = in.readInt();
- final int codecPriority = in.readInt();
- final int sampleRate = in.readInt();
- final int bitsPerSample = in.readInt();
- final int channelMode = in.readInt();
- final long codecSpecific1 = in.readLong();
- final long codecSpecific2 = in.readLong();
- final long codecSpecific3 = in.readLong();
- final long codecSpecific4 = in.readLong();
- return new BluetoothCodecConfig(codecType, codecPriority,
- sampleRate, bitsPerSample,
- channelMode, codecSpecific1,
- codecSpecific2, codecSpecific3,
- codecSpecific4);
+ return new BluetoothCodecConfig(in);
}
public BluetoothCodecConfig[] newArray(int size) {
@@ -368,8 +426,8 @@ public final class BluetoothCodecConfig implements Parcelable {
/**
* Flattens the object to a parcel
*
- * @param out The Parcel in which the object should be written.
- * @param flags Additional flags about how the object should be written.
+ * @param out The Parcel in which the object should be written
+ * @param flags Additional flags about how the object should be written
*
* @hide
*/
@@ -387,9 +445,8 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Gets the codec name.
- *
- * @return the codec name
+ * Returns the codec name converted to {@link String}.
+ * @hide
*/
public @NonNull String getCodecName() {
switch (mCodecType) {
@@ -412,137 +469,100 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Gets the codec type.
- * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
- *
- * @return the codec type
+ * Returns the source codec type of this config.
*/
- @UnsupportedAppUsage
public @SourceCodecType int getCodecType() {
return mCodecType;
}
/**
+ * Returns the valid codec types count.
+ */
+ public static int getMaxCodecType() {
+ return SOURCE_CODEC_TYPE_MAX;
+ }
+
+ /**
* Checks whether the codec is mandatory.
+ * <p> The actual mandatory codec type for Android Bluetooth audio is SBC.
+ * See {@link #SOURCE_CODEC_TYPE_SBC}.
*
- * @return true if the codec is mandatory, otherwise false.
+ * @return {@code true} if the codec is mandatory, {@code false} otherwise
+ * @hide
*/
public boolean isMandatoryCodec() {
return mCodecType == SOURCE_CODEC_TYPE_SBC;
}
/**
- * Gets the codec selection priority.
- * The codec selection priority is relative to other codecs: larger value
- * means higher priority. If 0, reset to default.
- *
- * @return the codec priority
+ * Returns the codec selection priority.
+ * <p>The codec selection priority is relative to other codecs: larger value
+ * means higher priority.
*/
- @UnsupportedAppUsage
public @CodecPriority int getCodecPriority() {
return mCodecPriority;
}
/**
* Sets the codec selection priority.
- * The codec selection priority is relative to other codecs: larger value
- * means higher priority. If 0, reset to default.
+ * <p>The codec selection priority is relative to other codecs: larger value
+ * means higher priority.
*
- * @param codecPriority the codec priority
+ * @param codecPriority the priority this codec should have
* @hide
*/
- @UnsupportedAppUsage
public void setCodecPriority(@CodecPriority int codecPriority) {
mCodecPriority = codecPriority;
}
/**
- * Gets the codec sample rate. The value can be a bitmask with all
- * supported sample rates:
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_48000} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_88200} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_96000} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_176400} or
- * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_192000}
- *
- * @return the codec sample rate
+ * Returns the codec sample rate. The value can be a bitmask with all
+ * supported sample rates.
*/
- @UnsupportedAppUsage
public @SampleRate int getSampleRate() {
return mSampleRate;
}
/**
- * Gets the codec bits per sample. The value can be a bitmask with all
- * bits per sample supported:
- * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
- * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
- * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_24} or
- * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_32}
- *
- * @return the codec bits per sample
+ * Returns the codec bits per sample. The value can be a bitmask with all
+ * bits per sample supported.
*/
- @UnsupportedAppUsage
public @BitsPerSample int getBitsPerSample() {
return mBitsPerSample;
}
/**
- * Gets the codec channel mode. The value can be a bitmask with all
- * supported channel modes:
- * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
- * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
- * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
- *
- * @return the codec channel mode
- * @hide
+ * Returns the codec channel mode. The value can be a bitmask with all
+ * supported channel modes.
*/
- @UnsupportedAppUsage
public @ChannelMode int getChannelMode() {
return mChannelMode;
}
/**
- * Gets a codec specific value1.
- *
- * @return a codec specific value1.
+ * Returns the codec specific value1.
*/
- @UnsupportedAppUsage
public long getCodecSpecific1() {
return mCodecSpecific1;
}
/**
- * Gets a codec specific value2.
- *
- * @return a codec specific value2
- * @hide
+ * Returns the codec specific value2.
*/
- @UnsupportedAppUsage
public long getCodecSpecific2() {
return mCodecSpecific2;
}
/**
- * Gets a codec specific value3.
- *
- * @return a codec specific value3
- * @hide
+ * Returns the codec specific value3.
*/
- @UnsupportedAppUsage
public long getCodecSpecific3() {
return mCodecSpecific3;
}
/**
- * Gets a codec specific value4.
- *
- * @return a codec specific value4
- * @hide
+ * Returns the codec specific value4.
*/
- @UnsupportedAppUsage
public long getCodecSpecific4() {
return mCodecSpecific4;
}
@@ -551,7 +571,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether a value set presented by a bitmask has zero or single bit
*
* @param valueSet the value set presented by a bitmask
- * @return true if the valueSet contains zero or single bit, otherwise false.
+ * @return {@code true} if the valueSet contains zero or single bit, {@code false} otherwise
* @hide
*/
private static boolean hasSingleBit(int valueSet) {
@@ -559,9 +579,7 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Checks whether the object contains none or single sample rate.
- *
- * @return true if the object contains none or single sample rate, otherwise false.
+ * Returns whether the object contains none or single sample rate.
* @hide
*/
public boolean hasSingleSampleRate() {
@@ -569,9 +587,7 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Checks whether the object contains none or single bits per sample.
- *
- * @return true if the object contains none or single bits per sample, otherwise false.
+ * Returns whether the object contains none or single bits per sample.
* @hide
*/
public boolean hasSingleBitsPerSample() {
@@ -579,9 +595,7 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Checks whether the object contains none or single channel mode.
- *
- * @return true if the object contains none or single channel mode, otherwise false.
+ * Returns whether the object contains none or single channel mode.
* @hide
*/
public boolean hasSingleChannelMode() {
@@ -589,10 +603,10 @@ public final class BluetoothCodecConfig implements Parcelable {
}
/**
- * Checks whether the audio feeding parameters are same.
+ * Checks whether the audio feeding parameters are the same.
*
* @param other the codec config to compare against
- * @return true if the audio feeding parameters are same, otherwise false
+ * @return {@code true} if the audio feeding parameters are same, {@code false} otherwise
* @hide
*/
public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
@@ -606,7 +620,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Any parameters with NONE value will be considered to be a wildcard matching.
*
* @param other the codec config to compare against
- * @return true if the audio feeding parameters are similar, otherwise false.
+ * @return {@code true} if the audio feeding parameters are similar, {@code false} otherwise
* @hide
*/
public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
@@ -614,18 +628,18 @@ public final class BluetoothCodecConfig implements Parcelable {
return false;
}
int sampleRate = other.mSampleRate;
- if (mSampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE
- || sampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
+ if (mSampleRate == SAMPLE_RATE_NONE
+ || sampleRate == SAMPLE_RATE_NONE) {
sampleRate = mSampleRate;
}
int bitsPerSample = other.mBitsPerSample;
- if (mBitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE
- || bitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
+ if (mBitsPerSample == BITS_PER_SAMPLE_NONE
+ || bitsPerSample == BITS_PER_SAMPLE_NONE) {
bitsPerSample = mBitsPerSample;
}
int channelMode = other.mChannelMode;
- if (mChannelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE
- || channelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
+ if (mChannelMode == CHANNEL_MODE_NONE
+ || channelMode == CHANNEL_MODE_NONE) {
channelMode = mChannelMode;
}
return sameAudioFeedingParameters(new BluetoothCodecConfig(
@@ -636,25 +650,158 @@ public final class BluetoothCodecConfig implements Parcelable {
/**
* Checks whether the codec specific parameters are the same.
+ * <p> Currently, only AAC VBR and LDAC Playback Quality on CodecSpecific1
+ * are compared.
*
* @param other the codec config to compare against
- * @return true if the codec specific parameters are the same, otherwise false.
+ * @return {@code true} if the codec specific parameters are the same, {@code false} otherwise
* @hide
*/
public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
if (other == null && mCodecType != other.mCodecType) {
return false;
}
- // Currently we only care about the AAC VBR and LDAC Playback Quality at CodecSpecific1
switch (mCodecType) {
case SOURCE_CODEC_TYPE_AAC:
case SOURCE_CODEC_TYPE_LDAC:
if (mCodecSpecific1 != other.mCodecSpecific1) {
return false;
}
- // fall through
default:
return true;
}
}
+
+ /**
+ * Builder for {@link BluetoothCodecConfig}.
+ * <p> By default, the codec type will be set to
+ * {@link BluetoothCodecConfig#SOURCE_CODEC_TYPE_INVALID}, the codec priority
+ * to {@link BluetoothCodecConfig#CODEC_PRIORITY_DEFAULT}, the sample rate to
+ * {@link BluetoothCodecConfig#SAMPLE_RATE_NONE}, the bits per sample to
+ * {@link BluetoothCodecConfig#BITS_PER_SAMPLE_NONE}, the channel mode to
+ * {@link BluetoothCodecConfig#CHANNEL_MODE_NONE}, and all the codec specific
+ * values to 0.
+ */
+ public static final class Builder {
+ private int mCodecType = BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+ private int mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
+ private int mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
+ private int mBitsPerSample = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE;
+ private int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE;
+ private long mCodecSpecific1 = 0;
+ private long mCodecSpecific2 = 0;
+ private long mCodecSpecific3 = 0;
+ private long mCodecSpecific4 = 0;
+
+ /**
+ * Set codec type for Bluetooth codec config.
+ *
+ * @param codecType of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
+ mCodecType = codecType;
+ return this;
+ }
+
+ /**
+ * Set codec priority for Bluetooth codec config.
+ *
+ * @param codecPriority of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecPriority(@CodecPriority int codecPriority) {
+ mCodecPriority = codecPriority;
+ return this;
+ }
+
+ /**
+ * Set sample rate for Bluetooth codec config.
+ *
+ * @param sampleRate of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setSampleRate(@SampleRate int sampleRate) {
+ mSampleRate = sampleRate;
+ return this;
+ }
+
+ /**
+ * Set the bits per sample for Bluetooth codec config.
+ *
+ * @param bitsPerSample of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setBitsPerSample(@BitsPerSample int bitsPerSample) {
+ mBitsPerSample = bitsPerSample;
+ return this;
+ }
+
+ /**
+ * Set the channel mode for Bluetooth codec config.
+ *
+ * @param channelMode of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setChannelMode(@ChannelMode int channelMode) {
+ mChannelMode = channelMode;
+ return this;
+ }
+
+ /**
+ * Set the first codec specific values for Bluetooth codec config.
+ *
+ * @param codecSpecific1 codec specific value or 0 if default
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecSpecific1(long codecSpecific1) {
+ mCodecSpecific1 = codecSpecific1;
+ return this;
+ }
+
+ /**
+ * Set the second codec specific values for Bluetooth codec config.
+ *
+ * @param codecSpecific2 codec specific value or 0 if default
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecSpecific2(long codecSpecific2) {
+ mCodecSpecific2 = codecSpecific2;
+ return this;
+ }
+
+ /**
+ * Set the third codec specific values for Bluetooth codec config.
+ *
+ * @param codecSpecific3 codec specific value or 0 if default
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecSpecific3(long codecSpecific3) {
+ mCodecSpecific3 = codecSpecific3;
+ return this;
+ }
+
+ /**
+ * Set the fourth codec specific values for Bluetooth codec config.
+ *
+ * @param codecSpecific4 codec specific value or 0 if default
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecSpecific4(long codecSpecific4) {
+ mCodecSpecific4 = codecSpecific4;
+ return this;
+ }
+
+ /**
+ * Build {@link BluetoothCodecConfig}.
+ * @return new BluetoothCodecConfig built
+ */
+ public @NonNull BluetoothCodecConfig build() {
+ return new BluetoothCodecConfig(mCodecType, mCodecPriority,
+ mSampleRate, mBitsPerSample,
+ mChannelMode, mCodecSpecific1,
+ mCodecSpecific2, mCodecSpecific3,
+ mCodecSpecific4);
+ }
+ }
}
diff --git a/framework/java/android/bluetooth/BluetoothCodecStatus.java b/framework/java/android/bluetooth/BluetoothCodecStatus.java
index 7764ebeb2e..02606feb3b 100644
--- a/framework/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/framework/java/android/bluetooth/BluetoothCodecStatus.java
@@ -16,12 +16,13 @@
package android.bluetooth;
+import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
/**
@@ -29,8 +30,6 @@ import java.util.Objects;
* A2DP source device.
*
* {@see BluetoothA2dp}
- *
- * {@hide}
*/
public final class BluetoothCodecStatus implements Parcelable {
/**
@@ -39,22 +38,27 @@ public final class BluetoothCodecStatus implements Parcelable {
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage
public static final String EXTRA_CODEC_STATUS =
"android.bluetooth.extra.CODEC_STATUS";
private final @Nullable BluetoothCodecConfig mCodecConfig;
- private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
- private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
+ private final @Nullable List<BluetoothCodecConfig> mCodecsLocalCapabilities;
+ private final @Nullable List<BluetoothCodecConfig> mCodecsSelectableCapabilities;
public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
- @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
- @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
+ @Nullable List<BluetoothCodecConfig> codecsLocalCapabilities,
+ @Nullable List<BluetoothCodecConfig> codecsSelectableCapabilities) {
mCodecConfig = codecConfig;
mCodecsLocalCapabilities = codecsLocalCapabilities;
mCodecsSelectableCapabilities = codecsSelectableCapabilities;
}
+ private BluetoothCodecStatus(Parcel in) {
+ mCodecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
+ mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
+ mCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothCodecConfig.CREATOR);
+ }
+
@Override
public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothCodecStatus) {
@@ -68,26 +72,25 @@ public final class BluetoothCodecStatus implements Parcelable {
}
/**
- * Checks whether two arrays of capabilities contain same capabilities.
- * The order of the capabilities in each array is ignored.
+ * Checks whether two lists of capabilities contain same capabilities.
+ * The order of the capabilities in each list is ignored.
*
- * @param c1 the first array of capabilities to compare
- * @param c2 the second array of capabilities to compare
- * @return true if both arrays contain same capabilities
- * @hide
+ * @param c1 the first list of capabilities to compare
+ * @param c2 the second list of capabilities to compare
+ * @return {@code true} if both lists contain same capabilities
*/
- public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
- BluetoothCodecConfig[] c2) {
+ private static boolean sameCapabilities(@Nullable List<BluetoothCodecConfig> c1,
+ @Nullable List<BluetoothCodecConfig> c2) {
if (c1 == null) {
return (c2 == null);
}
if (c2 == null) {
return false;
}
- if (c1.length != c2.length) {
+ if (c1.size() != c2.size()) {
return false;
}
- return Arrays.asList(c1).containsAll(Arrays.asList(c2));
+ return c1.containsAll(c2);
}
/**
@@ -95,10 +98,9 @@ public final class BluetoothCodecStatus implements Parcelable {
* Any parameters of the codec config with NONE value will be considered a wildcard matching.
*
* @param codecConfig the codec config to compare against
- * @return true if the codec config matches, otherwise false
- * @hide
+ * @return {@code true} if the codec config matches, {@code false} otherwise
*/
- public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
+ public boolean isCodecConfigSelectable(@Nullable BluetoothCodecConfig codecConfig) {
if (codecConfig == null || !codecConfig.hasSingleSampleRate()
|| !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) {
return false;
@@ -128,10 +130,7 @@ public final class BluetoothCodecStatus implements Parcelable {
}
/**
- * Returns a hash based on the codec config and local capabilities
- *
- * @return a hash based on the config values
- * @hide
+ * Returns a hash based on the codec config and local capabilities.
*/
@Override
public int hashCode() {
@@ -139,17 +138,19 @@ public final class BluetoothCodecStatus implements Parcelable {
mCodecsLocalCapabilities);
}
+ /**
+ * Returns a {@link String} that describes each BluetoothCodecStatus parameter
+ * current value.
+ */
@Override
public String toString() {
return "{mCodecConfig:" + mCodecConfig
- + ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities)
- + ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities)
+ + ",mCodecsLocalCapabilities:" + mCodecsLocalCapabilities
+ + ",mCodecsSelectableCapabilities:" + mCodecsSelectableCapabilities
+ "}";
}
/**
- * Always returns 0
- *
* @return 0
* @hide
*/
@@ -161,16 +162,7 @@ public final class BluetoothCodecStatus implements Parcelable {
public static final @android.annotation.NonNull Parcelable.Creator<BluetoothCodecStatus> CREATOR =
new Parcelable.Creator<BluetoothCodecStatus>() {
public BluetoothCodecStatus createFromParcel(Parcel in) {
- final BluetoothCodecConfig codecConfig = in.readTypedObject(
- BluetoothCodecConfig.CREATOR);
- final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray(
- BluetoothCodecConfig.CREATOR);
- final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray(
- BluetoothCodecConfig.CREATOR);
-
- return new BluetoothCodecStatus(codecConfig,
- codecsLocalCapabilities,
- codecsSelectableCapabilities);
+ return new BluetoothCodecStatus(in);
}
public BluetoothCodecStatus[] newArray(int size) {
@@ -179,47 +171,38 @@ public final class BluetoothCodecStatus implements Parcelable {
};
/**
- * Flattens the object to a parcel
+ * Flattens the object to a parcel.
*
- * @param out The Parcel in which the object should be written.
- * @param flags Additional flags about how the object should be written.
- *
- * @hide
+ * @param out The Parcel in which the object should be written
+ * @param flags Additional flags about how the object should be written
*/
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeTypedObject(mCodecConfig, 0);
- out.writeTypedArray(mCodecsLocalCapabilities, 0);
- out.writeTypedArray(mCodecsSelectableCapabilities, 0);
+ out.writeTypedList(mCodecsLocalCapabilities);
+ out.writeTypedList(mCodecsSelectableCapabilities);
}
/**
- * Gets the current codec configuration.
- *
- * @return the current codec configuration
+ * Returns the current codec configuration.
*/
- @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
/**
- * Gets the codecs local capabilities.
- *
- * @return an array with the codecs local capabilities
+ * Returns the codecs local capabilities.
*/
- @UnsupportedAppUsage
- public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
- return mCodecsLocalCapabilities;
+ public @NonNull List<BluetoothCodecConfig> getCodecsLocalCapabilities() {
+ return (mCodecsLocalCapabilities == null)
+ ? Collections.emptyList() : mCodecsLocalCapabilities;
}
/**
- * Gets the codecs selectable capabilities.
- *
- * @return an array with the codecs selectable capabilities
+ * Returns the codecs selectable capabilities.
*/
- @UnsupportedAppUsage
- public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
- return mCodecsSelectableCapabilities;
+ public @NonNull List<BluetoothCodecConfig> getCodecsSelectableCapabilities() {
+ return (mCodecsSelectableCapabilities == null)
+ ? Collections.emptyList() : mCodecsSelectableCapabilities;
}
}
diff --git a/framework/java/android/bluetooth/BluetoothGattServer.java b/framework/java/android/bluetooth/BluetoothGattServer.java
index 3e799defa5..08e0178403 100644
--- a/framework/java/android/bluetooth/BluetoothGattServer.java
+++ b/framework/java/android/bluetooth/BluetoothGattServer.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
@@ -26,6 +28,8 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -709,33 +713,85 @@ public final class BluetoothGattServer implements BluetoothProfile {
* notification
* @return true, if the notification has been triggered successfully
* @throws IllegalArgumentException
+ *
+ * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
+ * BluetoothGattCharacteristic, boolean, byte[])} as this is not memory safe.
*/
+ @Deprecated
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean notifyCharacteristicChanged(BluetoothDevice device,
BluetoothGattCharacteristic characteristic, boolean confirm) {
+ return notifyCharacteristicChanged(device, characteristic, confirm,
+ characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
+ BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+ BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
+ BluetoothStatusCodes.ERROR_UNKNOWN
+ })
+ public @interface NotifyCharacteristicReturnValues{}
+
+ /**
+ * Send a notification or indication that a local characteristic has been
+ * updated.
+ *
+ * <p>A notification or indication is sent to the remote device to signal
+ * that the characteristic has been updated. This function should be invoked
+ * for every client that requests notifications/indications by writing
+ * to the "Client Configuration" descriptor for the given characteristic.
+ *
+ * @param device the remote device to receive the notification/indication
+ * @param characteristic the local characteristic that has been updated
+ * @param confirm {@code true} to request confirmation from the client (indication) or
+ * {@code false} to send a notification
+ * @param value the characteristic value
+ * @return whether the notification has been triggered successfully
+ * @throws IllegalArgumentException if the characteristic value or service is null
+ */
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @NotifyCharacteristicReturnValues
+ public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
+ @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
+ @NonNull byte[] value) {
if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
- if (mService == null || mServerIf == 0) return false;
+ if (mService == null || mServerIf == 0) {
+ return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+ }
+ if (characteristic == null) {
+ throw new IllegalArgumentException("characteristic must not be null");
+ }
+ if (device == null) {
+ throw new IllegalArgumentException("device must not be null");
+ }
BluetoothGattService service = characteristic.getService();
- if (service == null) return false;
-
- if (characteristic.getValue() == null) {
- throw new IllegalArgumentException("Chracteristic value is empty. Use "
- + "BluetoothGattCharacteristic#setvalue to update");
+ if (service == null) {
+ throw new IllegalArgumentException("Characteristic must have a non-null service");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("Characteristic value must not be null");
}
try {
- mService.sendNotification(mServerIf, device.getAddress(),
+ return mService.sendNotification(mServerIf, device.getAddress(),
characteristic.getInstanceId(), confirm,
- characteristic.getValue(), mAttributionSource);
+ value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
- return false;
+ throw e.rethrowFromSystemServer();
}
-
- return true;
}
/**
diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
new file mode 100644
index 0000000000..dcaf4b682f
--- /dev/null
+++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2021 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.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Represents the codec configuration for a Bluetooth LE Audio source device.
+ * <p>Contains the source codec type.
+ * <p>The source codec type values are the same as those supported by the
+ * device hardware.
+ *
+ * {@see BluetoothLeAudioCodecConfig}
+ */
+public final class BluetoothLeAudioCodecConfig {
+ // Add an entry for each source codec here.
+
+ /** @hide */
+ @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+ SOURCE_CODEC_TYPE_LC3,
+ SOURCE_CODEC_TYPE_INVALID
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceCodecType {};
+
+ public static final int SOURCE_CODEC_TYPE_LC3 = 0;
+ public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+
+ /**
+ * Represents the count of valid source codec types. Can be accessed via
+ * {@link #getMaxCodecType}.
+ */
+ private static final int SOURCE_CODEC_TYPE_MAX = 1;
+
+ private final @SourceCodecType int mCodecType;
+
+ /**
+ * Creates a new BluetoothLeAudioCodecConfig.
+ *
+ * @param codecType the source codec type
+ */
+ private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType) {
+ mCodecType = codecType;
+ }
+
+ @Override
+ public String toString() {
+ return "{codecName:" + getCodecName() + "}";
+ }
+
+ /**
+ * Gets the codec type.
+ *
+ * @return the codec type
+ */
+ public @SourceCodecType int getCodecType() {
+ return mCodecType;
+ }
+
+ /**
+ * Returns the valid codec types count.
+ */
+ public static int getMaxCodecType() {
+ return SOURCE_CODEC_TYPE_MAX;
+ }
+
+ /**
+ * Gets the codec name.
+ *
+ * @return the codec name
+ */
+ public @NonNull String getCodecName() {
+ switch (mCodecType) {
+ case SOURCE_CODEC_TYPE_LC3:
+ return "LC3";
+ case SOURCE_CODEC_TYPE_INVALID:
+ return "INVALID CODEC";
+ default:
+ break;
+ }
+ return "UNKNOWN CODEC(" + mCodecType + ")";
+ }
+
+ /**
+ * Builder for {@link BluetoothLeAudioCodecConfig}.
+ * <p> By default, the codec type will be set to
+ * {@link BluetoothLeAudioCodecConfig#SOURCE_CODEC_TYPE_INVALID}
+ */
+ public static final class Builder {
+ private int mCodecType = BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_INVALID;
+
+ /**
+ * Set codec type for Bluetooth codec config.
+ *
+ * @param codecType of this codec
+ * @return the same Builder instance
+ */
+ public @NonNull Builder setCodecType(@SourceCodecType int codecType) {
+ mCodecType = codecType;
+ return this;
+ }
+
+ /**
+ * Build {@link BluetoothLeAudioCodecConfig}.
+ * @return new BluetoothLeAudioCodecConfig built
+ */
+ public @NonNull BluetoothLeAudioCodecConfig build() {
+ return new BluetoothLeAudioCodecConfig(mCodecType);
+ }
+ }
+}
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcast.java b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
new file mode 100644
index 0000000000..fed9f911d5
--- /dev/null
+++ b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2021 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.IntDef;
+import android.content.Context;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the Bluetooth LE Broadcast Source profile.
+ *
+ * <p>BluetoothLeBroadcast is a proxy object for controlling the Bluetooth LE Broadcast
+ * Source Service via IPC. Use {@link BluetoothAdapter#getProfileProxy}
+ * to get the BluetoothLeBroadcast proxy object.
+ *
+ * @hide
+ */
+public final class BluetoothLeBroadcast implements BluetoothProfile {
+ private static final String TAG = "BluetoothLeBroadcast";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /**
+ * Constants used by the LE Audio Broadcast profile for the Broadcast state
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"LE_AUDIO_BROADCAST_STATE_"}, value = {
+ LE_AUDIO_BROADCAST_STATE_DISABLED,
+ LE_AUDIO_BROADCAST_STATE_ENABLING,
+ LE_AUDIO_BROADCAST_STATE_ENABLED,
+ LE_AUDIO_BROADCAST_STATE_DISABLING,
+ LE_AUDIO_BROADCAST_STATE_PLAYING,
+ LE_AUDIO_BROADCAST_STATE_NOT_PLAYING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LeAudioBroadcastState {}
+
+ /**
+ * Indicates that LE Audio Broadcast mode is currently disabled
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_DISABLED = 10;
+
+ /**
+ * Indicates that LE Audio Broadcast mode is being enabled
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_ENABLING = 11;
+
+ /**
+ * Indicates that LE Audio Broadcast mode is currently enabled
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_ENABLED = 12;
+ /**
+ * Indicates that LE Audio Broadcast mode is being disabled
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_DISABLING = 13;
+
+ /**
+ * Indicates that an LE Audio Broadcast mode is currently playing
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_PLAYING = 14;
+
+ /**
+ * Indicates that LE Audio Broadcast is currently not playing
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_STATE_NOT_PLAYING = 15;
+
+ /**
+ * Constants used by the LE Audio Broadcast profile for encryption key length
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"LE_AUDIO_BROADCAST_ENCRYPTION_KEY_"}, value = {
+ LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT,
+ LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LeAudioEncryptionKeyLength {}
+
+ /**
+ * Indicates that the LE Audio Broadcast encryption key size is 32 bits.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_32BIT = 16;
+
+ /**
+ * Indicates that the LE Audio Broadcast encryption key size is 128 bits.
+ *
+ * @hide
+ */
+ public static final int LE_AUDIO_BROADCAST_ENCRYPTION_KEY_128BIT = 17;
+
+ /**
+ * Interface for receiving events related to broadcasts
+ */
+ public interface Callback {
+ /**
+ * Called when broadcast state has changed
+ *
+ * @param prevState broadcast state before the change
+ * @param newState broadcast state after the change
+ */
+ @LeAudioBroadcastState
+ void onBroadcastStateChange(int prevState, int newState);
+ /**
+ * Called when encryption key has been updated
+ *
+ * @param success true if the key was updated successfully, false otherwise
+ */
+ void onEncryptionKeySet(boolean success);
+ }
+
+ /**
+ * Create a BluetoothLeBroadcast proxy object for interacting with the local
+ * LE Audio Broadcast Source service.
+ *
+ * @hide
+ */
+ /*package*/ BluetoothLeBroadcast(Context context,
+ BluetoothProfile.ServiceListener listener) {
+ }
+
+ /**
+ * Not supported since LE Audio Broadcasts do not establish a connection
+ *
+ * @throws UnsupportedOperationException
+ *
+ * @hide
+ */
+ @Override
+ public int getConnectionState(BluetoothDevice device) {
+ throw new UnsupportedOperationException(
+ "LE Audio Broadcasts are not connection-oriented.");
+ }
+
+ /**
+ * Not supported since LE Audio Broadcasts do not establish a connection
+ *
+ * @throws UnsupportedOperationException
+ *
+ * @hide
+ */
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ throw new UnsupportedOperationException(
+ "LE Audio Broadcasts are not connection-oriented.");
+ }
+
+ /**
+ * Not supported since LE Audio Broadcasts do not establish a connection
+ *
+ * @throws UnsupportedOperationException
+ *
+ * @hide
+ */
+ @Override
+ public List<BluetoothDevice> getConnectedDevices() {
+ throw new UnsupportedOperationException(
+ "LE Audio Broadcasts are not connection-oriented.");
+ }
+
+ /**
+ * Enable LE Audio Broadcast mode.
+ *
+ * Generates a new broadcast ID and enables sending of encrypted or unencrypted
+ * isochronous PDUs
+ *
+ * @hide
+ */
+ public int enableBroadcastMode() {
+ if (DBG) log("enableBroadcastMode");
+ return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
+ }
+
+ /**
+ * Disable LE Audio Broadcast mode.
+ *
+ * @hide
+ */
+ public int disableBroadcastMode() {
+ if (DBG) log("disableBroadcastMode");
+ return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED;
+ }
+
+ /**
+ * Get the current LE Audio broadcast state
+ *
+ * @hide
+ */
+ @LeAudioBroadcastState
+ public int getBroadcastState() {
+ if (DBG) log("getBroadcastState");
+ return LE_AUDIO_BROADCAST_STATE_DISABLED;
+ }
+
+ /**
+ * Enable LE Audio broadcast encryption
+ *
+ * @param keyLength if useExisting is true, this specifies the length of the key that should
+ * be generated
+ * @param useExisting true, if an existing key should be used
+ * false, if a new key should be generated
+ *
+ * @hide
+ */
+ @LeAudioEncryptionKeyLength
+ public int enableEncryption(boolean useExisting, int keyLength) {
+ if (DBG) log("enableEncryption useExisting=" + useExisting + " keyLength=" + keyLength);
+ return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED;
+ }
+
+ /**
+ * Disable LE Audio broadcast encryption
+ *
+ * @param removeExisting true, if the existing key should be removed
+ * false, otherwise
+ *
+ * @hide
+ */
+ public int disableEncryption(boolean removeExisting) {
+ if (DBG) log("disableEncryption removeExisting=" + removeExisting);
+ return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED;
+ }
+
+ /**
+ * Enable or disable LE Audio broadcast encryption
+ *
+ * @param key use the provided key if non-null, generate a new key if null
+ * @param keyLength 0 if encryption is disabled, 4 bytes (low security),
+ * 16 bytes (high security)
+ *
+ * @hide
+ */
+ @LeAudioEncryptionKeyLength
+ public int setEncryptionKey(byte[] key, int keyLength) {
+ if (DBG) log("setEncryptionKey key=" + key + " keyLength=" + keyLength);
+ return BluetoothStatusCodes.ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED;
+ }
+
+
+ /**
+ * Get the encryption key that was set before
+ *
+ * @return encryption key as a byte array or null if no encryption key was set
+ *
+ * @hide
+ */
+ public byte[] getEncryptionKey() {
+ if (DBG) log("getEncryptionKey");
+ return null;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/framework/java/android/bluetooth/BluetoothProfile.java b/framework/java/android/bluetooth/BluetoothProfile.java
index 0cf9f9fd6f..e047e5d81a 100644
--- a/framework/java/android/bluetooth/BluetoothProfile.java
+++ b/framework/java/android/bluetooth/BluetoothProfile.java
@@ -233,12 +233,19 @@ public interface BluetoothProfile {
int CSIP_SET_COORDINATOR = 25;
/**
+ * LE Audio Broadcast Source
+ *
+ * @hide
+ */
+ int LE_AUDIO_BROADCAST = 26;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- int MAX_PROFILE_ID = 25;
+ int MAX_PROFILE_ID = 26;
/**
* Default priority for devices that we try to auto-connect to and
@@ -436,6 +443,8 @@ public interface BluetoothProfile {
return "OPP";
case HEARING_AID:
return "HEARING_AID";
+ case LE_AUDIO:
+ return "LE_AUDIO";
default:
return "UNKNOWN_PROFILE";
}
diff --git a/framework/java/android/bluetooth/BluetoothSocket.java b/framework/java/android/bluetooth/BluetoothSocket.java
index 1655b62bbf..db5b75148e 100644
--- a/framework/java/android/bluetooth/BluetoothSocket.java
+++ b/framework/java/android/bluetooth/BluetoothSocket.java
@@ -18,7 +18,6 @@ package android.bluetooth;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.LocalSocket;
@@ -266,7 +265,7 @@ public final class BluetoothSocket implements Closeable {
throw new IOException("bt socket acept failed");
}
- as.mPfd = new ParcelFileDescriptor(fds[0]);
+ as.mPfd = ParcelFileDescriptor.dup(fds[0]);
as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
as.mSocketIS = as.mSocket.getInputStream();
as.mSocketOS = as.mSocket.getOutputStream();
diff --git a/framework/java/android/bluetooth/BluetoothStatusCodes.java b/framework/java/android/bluetooth/BluetoothStatusCodes.java
index ca01784efd..9dafa073ab 100644
--- a/framework/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java
@@ -226,6 +226,66 @@ public final class BluetoothStatusCodes {
public static final int ERROR_DISCONNECT_REASON_BAD_PARAMETERS = 1109;
/**
+ * Indicates that setting the LE Audio Broadcast mode failed.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_BROADCAST_MODE_FAILED = 1110;
+
+ /**
+ * Indicates that setting a new encryption key for Bluetooth LE Audio Broadcast Source failed.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_SET_ENCRYPTION_KEY_FAILED = 1111;
+
+ /**
+ * Indicates that connecting to a remote Broadcast Audio Scan Service failed.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_CONNECT_FAILED = 1112;
+
+ /**
+ * Indicates that disconnecting from a remote Broadcast Audio Scan Service failed.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_AUDIO_SCAN_SERVICE_DISCONNECT_FAILED = 1113;
+
+ /**
+ * Indicates that enabling LE Audio Broadcast encryption failed
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_ENABLE_ENCRYPTION_FAILED = 1114;
+
+ /**
+ * Indicates that disabling LE Audio Broadcast encryption failed
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ *
+ * @hide
+ */
+ public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115;
+
+ /**
* Indicates that an unknown error has occurred has occurred.
*/
public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;