Add BluetoothLeBroadcast profile API.

Implementation for the APIs will be added later.

Bug: 205174140
Bug: 208222281
Tag: #feature
Test: gd/cert/run

Change-Id: I8781be89cba45a6e7a76fec7df24790a9f02d6a6
diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcast.java b/framework/java/android/bluetooth/BluetoothLeBroadcast.java
new file mode 100644
index 0000000..fed9f91
--- /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 0cf9f9f..7f96958 100644
--- a/framework/java/android/bluetooth/BluetoothProfile.java
+++ b/framework/java/android/bluetooth/BluetoothProfile.java
@@ -233,12 +233,19 @@
     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
diff --git a/framework/java/android/bluetooth/BluetoothStatusCodes.java b/framework/java/android/bluetooth/BluetoothStatusCodes.java
index ca01784..9dafa07 100644
--- a/framework/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/framework/java/android/bluetooth/BluetoothStatusCodes.java
@@ -226,6 +226,66 @@
     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;