diff options
30 files changed, 704 insertions, 259 deletions
diff --git a/android/app/jni/com_android_bluetooth_le_audio.cpp b/android/app/jni/com_android_bluetooth_le_audio.cpp index 0e61a80c4e..ea435c77c0 100644 --- a/android/app/jni/com_android_bluetooth_le_audio.cpp +++ b/android/app/jni/com_android_bluetooth_le_audio.cpp @@ -158,7 +158,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { jclass jniBluetoothLeAudioCodecConfigClass = env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfig"); android_bluetooth_BluetoothLeAudioCodecConfig.constructor = env->GetMethodID( - jniBluetoothLeAudioCodecConfigClass, "<init>", "(IIIIIII)V"); + jniBluetoothLeAudioCodecConfigClass, "<init>", "(IIIIIIIII)V"); android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType = env->GetMethodID( jniBluetoothLeAudioCodecConfigClass, "getCodecType", "()I"); @@ -355,6 +355,21 @@ static void groupSetActiveNative(JNIEnv* env, jobject object, jint group_id) { sLeAudioClientInterface->GroupSetActive(group_id); } +static void setCodecConfigPreferenceNative(JNIEnv* env, jobject object, + jint group_id, + jobject inputCodecConfig, + jobject outputCodecConfig) { + if (!env->IsInstanceOf(inputCodecConfig, + android_bluetooth_BluetoothLeAudioCodecConfig.clazz) || + !env->IsInstanceOf(outputCodecConfig, + android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) { + ALOGE("%s: Invalid BluetoothLeAudioCodecConfig instance", __func__); + return; + } + + // TODO Implement +} + static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V", @@ -365,6 +380,10 @@ static JNINativeMethod sMethods[] = { {"groupAddNodeNative", "(I[B)Z", (void*)groupAddNodeNative}, {"groupRemoveNodeNative", "(I[B)Z", (void*)groupRemoveNodeNative}, {"groupSetActiveNative", "(I)V", (void*)groupSetActiveNative}, + {"setCodecConfigPreferenceNative", + "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;Landroid/bluetooth/" + "BluetoothLeAudioCodecConfig;)V", + (void*)setCodecConfigPreferenceNative}, }; /* Le Audio Broadcaster */ diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 1a5e7a5a73..fe3209c120 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -55,6 +55,7 @@ import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUuid; import android.bluetooth.BufferConstraints; import android.bluetooth.IBluetooth; +import android.bluetooth.IBluetoothActivityEnergyInfoListener; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothConnectionCallback; import android.bluetooth.IBluetoothMetadataListener; @@ -84,7 +85,6 @@ import android.os.ParcelUuid; import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ResultReceiver; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; @@ -217,8 +217,6 @@ public class AdapterService extends Service { public static final String ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS = "no_active_device_address"; - public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity"; - // Report ID definition public enum BqrQualityReportId { QUALITY_REPORT_ID_MONITOR_MODE(0x01), @@ -3600,11 +3598,14 @@ public class AdapterService extends Service { } @Override - public void requestActivityInfo(ResultReceiver result, AttributionSource source) { - Bundle bundle = new Bundle(); - bundle.putParcelable(RESULT_RECEIVER_CONTROLLER_KEY, - reportActivityInfo(source)); - result.send(0, bundle); + public void requestActivityInfo(IBluetoothActivityEnergyInfoListener listener, + AttributionSource source) { + BluetoothActivityEnergyInfo info = reportActivityInfo(source); + try { + listener.onBluetoothActivityEnergyInfo(info); + } catch (RemoteException e) { + Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e); + } } @Override diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 6967511700..1df37713eb 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -1776,7 +1776,9 @@ public class GattService extends ProfileService { for (ScanClient client : mScanManager.getRegularScanQueue()) { ScannerMap.App app = mScannerMap.getById(client.scannerId); if (app == null) { - Log.i(TAG, "App is null; skip."); + if (VDBG) { + Log.d(TAG, "App is null; skip."); + } continue; } @@ -1788,7 +1790,9 @@ public class GattService extends ProfileService { if (settings.getLegacy()) { if ((eventType & ET_LEGACY_MASK) == 0) { // If this is legacy scan, but nonlegacy result - skip. - Log.i(TAG, "Legacy scan, non legacy result; skip."); + if (VDBG) { + Log.d(TAG, "Legacy scan, non legacy result; skip."); + } continue; } else { // Some apps are used to fixed-size advertise data. @@ -1829,8 +1833,10 @@ public class GattService extends ProfileService { } MatchResult matchResult = matchesFilters(client, result, originalAddress); if (!hasPermission || !matchResult.getMatches()) { - Log.i(TAG, "Skipping client: permission=" - + hasPermission + " matches=" + matchResult.getMatches()); + if (VDBG) { + Log.d(TAG, "Skipping client: permission=" + + hasPermission + " matches=" + matchResult.getMatches()); + } continue; } @@ -1842,7 +1848,9 @@ public class GattService extends ProfileService { } if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) { - Log.i(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); + if (VDBG) { + Log.d(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); + } continue; } diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioNativeInterface.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioNativeInterface.java index 46e2db2202..6dfc627f83 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioNativeInterface.java @@ -215,6 +215,18 @@ public class LeAudioNativeInterface { groupSetActiveNative(groupId); } + /** + * Set codec config preference. + * @param groupId group ID for the preference + * @param inputCodecConfig input codec configuration + * @param outputCodecConfig output codec configuration + */ + public void setCodecConfigPreference(int groupId, + BluetoothLeAudioCodecConfig inputCodecConfig, + BluetoothLeAudioCodecConfig outputCodecConfig) { + setCodecConfigPreferenceNative(groupId, inputCodecConfig, outputCodecConfig); + } + // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(BluetoothLeAudioCodecConfig[] codecConfigOffloading); @@ -224,4 +236,7 @@ public class LeAudioNativeInterface { private native boolean groupAddNodeNative(int groupId, byte[] address); private native boolean groupRemoveNodeNative(int groupId, byte[] address); private native void groupSetActiveNative(int groupId); + private native void setCodecConfigPreferenceNative(int groupId, + BluetoothLeAudioCodecConfig inputCodecConfig, + BluetoothLeAudioCodecConfig outputCodecConfig); } diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index e6fc534de5..5e1834efff 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -132,11 +132,13 @@ public class LeAudioService extends ProfileService { mIsConnected = false; mIsActive = false; mActiveContexts = ACTIVE_CONTEXTS_NONE; + mCodecStatus = null; } public Boolean mIsConnected; public Boolean mIsActive; public Integer mActiveContexts; + public BluetoothLeAudioCodecStatus mCodecStatus; } private final Map<Integer, LeAudioGroupDescriptor> mGroupDescriptors = new LinkedHashMap<>(); @@ -1726,46 +1728,64 @@ public class LeAudioService extends ProfileService { /** * Gets the current codec status (configuration and capability). * - * @param device the remote Bluetooth device. + * @param groupId the group id * @return the current codec status * @hide */ - public BluetoothLeAudioCodecStatus getCodecStatus(BluetoothDevice device) { + public BluetoothLeAudioCodecStatus getCodecStatus(int groupId) { if (DBG) { - Log.d(TAG, "getCodecStatus(" + device + ")"); + Log.d(TAG, "getCodecStatus(" + groupId + ")"); + } + LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(groupId); + if (descriptor != null) { + return descriptor.mCodecStatus; } - return null; } /** * Sets the codec configuration preference. * - * @param device the remote Bluetooth device. - * @param codecConfig the codec configuration preference + * @param groupId the group id + * @param inputCodecConfig the input codec configuration preference + * @param outputCodecConfig the output codec configuration preference * @hide */ - public void setCodecConfigPreference(BluetoothDevice device, - BluetoothLeAudioCodecConfig codecConfig) { + public void setCodecConfigPreference(int groupId, + BluetoothLeAudioCodecConfig inputCodecConfig, + BluetoothLeAudioCodecConfig outputCodecConfig) { if (DBG) { - Log.d(TAG, "setCodecConfigPreference(" + device + "): " - + Objects.toString(codecConfig)); + Log.d(TAG, "setCodecConfigPreference(" + groupId + "): " + + Objects.toString(inputCodecConfig) + + Objects.toString(outputCodecConfig)); } - if (device == null) { - Log.e(TAG, "setCodecConfigPreference: Invalid device"); + LeAudioGroupDescriptor descriptor = mGroupDescriptors.get(groupId); + if (descriptor == null) { + Log.e(TAG, "setCodecConfigPreference: Invalid groupId, " + groupId); return; } - if (codecConfig == null) { + + if (inputCodecConfig == null || outputCodecConfig == null) { Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); return; } - BluetoothLeAudioCodecStatus codecStatus = getCodecStatus(device); - if (codecStatus == null) { + + /* We support different configuration for input and output but codec type + * shall be same */ + if (inputCodecConfig.getCodecType() != outputCodecConfig.getCodecType()) { + Log.e(TAG, "setCodecConfigPreference: Input codec type: " + + inputCodecConfig.getCodecType() + + "does not match output codec type: " + outputCodecConfig.getCodecType()); + return; + } + + if (descriptor.mCodecStatus == null) { Log.e(TAG, "setCodecConfigPreference: Codec status is null"); return; } - // TODO: pass the information to bt stack + mLeAudioNativeInterface.setCodecConfigPreference(groupId, + inputCodecConfig, outputCodecConfig); } @@ -2185,14 +2205,14 @@ public class LeAudioService extends ProfileService { } @Override - public void getCodecStatus(BluetoothDevice device, + public void getCodecStatus(int groupId, AttributionSource source, SynchronousResultReceiver receiver) { try { LeAudioService service = getService(source); BluetoothLeAudioCodecStatus codecStatus = null; if (service != null) { enforceBluetoothPrivilegedPermission(service); - codecStatus = service.getCodecStatus(device); + codecStatus = service.getCodecStatus(groupId); } receiver.send(codecStatus); } catch (RuntimeException e) { @@ -2201,15 +2221,17 @@ public class LeAudioService extends ProfileService { } @Override - public void setCodecConfigPreference(BluetoothDevice device, - BluetoothLeAudioCodecConfig codecConfig, AttributionSource source) { + public void setCodecConfigPreference(int groupId, + BluetoothLeAudioCodecConfig inputCodecConfig, + BluetoothLeAudioCodecConfig outputCodecConfig, + AttributionSource source) { LeAudioService service = getService(source); if (service == null) { return; } enforceBluetoothPrivilegedPermission(service); - service.setCodecConfigPreference(device, codecConfig); + service.setCodecConfigPreference(groupId, inputCodecConfig, outputCodecConfig); } } diff --git a/android/app/src/com/android/bluetooth/mcp/McpService.java b/android/app/src/com/android/bluetooth/mcp/McpService.java index 2508b2f38f..34f413882c 100644 --- a/android/app/src/com/android/bluetooth/mcp/McpService.java +++ b/android/app/src/com/android/bluetooth/mcp/McpService.java @@ -26,6 +26,7 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.ProfileService; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.HashMap; @@ -41,8 +42,11 @@ public class McpService extends ProfileService { private static final String TAG = "BluetoothMcpService"; private static McpService sMcpService; + private static MediaControlProfile sGmcsForTesting; - private static MediaControlProfile sGmcs; + private Object mLock = new Object(); + @GuardedBy("mLock") + private MediaControlProfile mGmcs; private Map<BluetoothDevice, Integer> mDeviceAuthorizations = new HashMap<>(); private Handler mHandler = new Handler(Looper.getMainLooper()); @@ -68,11 +72,12 @@ public class McpService extends ProfileService { @VisibleForTesting public static MediaControlProfile getMediaControlProfile() { - return sGmcs; + return sGmcsForTesting; } + @VisibleForTesting public static void setMediaControlProfileForTesting(MediaControlProfile mediaControlProfile) { - sGmcs = mediaControlProfile; + sGmcsForTesting = mediaControlProfile; } @Override @@ -100,11 +105,19 @@ public class McpService extends ProfileService { // Mark service as started setMcpService(this); - if (sGmcs == null) { - // Initialize the Media Control Service Server - sGmcs = new MediaControlProfile(this); - // Requires this service to be already started thus we have to make it an async call - mHandler.post(() -> sGmcs.init()); + synchronized (mLock) { + if (getGmcsLocked() == null) { + // Initialize the Media Control Service Server + mGmcs = new MediaControlProfile(this); + // Requires this service to be already started thus we have to make it an async call + mHandler.post(() -> { + synchronized (mLock) { + if (mGmcs != null) { + mGmcs.init(); + } + } + }); + } } return true; @@ -121,9 +134,17 @@ public class McpService extends ProfileService { return true; } - if (sGmcs != null) { - sGmcs.cleanup(); - sGmcs = null; + synchronized (mLock) { + // A runnable for calling mGmcs.init() could be pending on mHandler + mHandler.removeCallbacksAndMessages(null); + if (mGmcs != null) { + mGmcs.cleanup(); + mGmcs = null; + } + if (sGmcsForTesting != null) { + sGmcsForTesting.cleanup(); + sGmcsForTesting = null; + } } // Mark service as stopped @@ -138,6 +159,17 @@ public class McpService extends ProfileService { } } + @Override + public void dump(StringBuilder sb) { + super.dump(sb); + synchronized (mLock) { + MediaControlProfile gmcs = getGmcsLocked(); + if (gmcs != null) { + gmcs.dump(sb); + } + } + } + public void onDeviceUnauthorized(BluetoothDevice device) { Log.w(TAG, "onDeviceUnauthorized - authorization notification not implemented yet "); } @@ -148,7 +180,12 @@ public class McpService extends ProfileService { : BluetoothDevice.ACCESS_REJECTED; mDeviceAuthorizations.put(device, authorization); - sGmcs.onDeviceAuthorizationSet(device); + synchronized (mLock) { + MediaControlProfile gmcs = getGmcsLocked(); + if (gmcs != null) { + gmcs.onDeviceAuthorizationSet(device); + } + } } public int getDeviceAuthorization(BluetoothDevice device) { @@ -157,6 +194,15 @@ public class McpService extends ProfileService { return mDeviceAuthorizations.getOrDefault(device, BluetoothDevice.ACCESS_UNKNOWN); } + @GuardedBy("mLock") + private MediaControlProfile getGmcsLocked() { + if (sGmcsForTesting != null) { + return sGmcsForTesting; + } else { + return mGmcs; + } + } + /** * Binder object: must be a static class or memory leak may occur */ @@ -195,10 +241,4 @@ public class McpService extends ProfileService { mService = null; } } - - @Override - public void dump(StringBuilder sb) { - super.dump(sb); - sGmcs.dump(sb); - } } diff --git a/framework/api/current.txt b/framework/api/current.txt index b2dc4367f1..cf4c4b18f6 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -930,21 +930,23 @@ package android.bluetooth { public final class BluetoothLeAudioCodecConfig implements android.os.Parcelable { method public int describeContents(); method public int getBitsPerSample(); - method public int getChannelMode(); + method public int getChannelCount(); method @NonNull public String getCodecName(); method public int getCodecPriority(); method public int getCodecType(); method public int getFrameDuration(); + method public int getMaxOctetsPerFrame(); + method public int getMinOctetsPerFrame(); method public int getOctetsPerFrame(); method public int getSampleRate(); method public void writeToParcel(@NonNull android.os.Parcel, int); field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1 field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2 - field public static final int BITS_PER_SAMPLE_32 = 3; // 0x3 + field public static final int BITS_PER_SAMPLE_32 = 8; // 0x8 field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0 - field public static final int CHANNEL_MODE_MONO = 1; // 0x1 - field public static final int CHANNEL_MODE_NONE = 0; // 0x0 - field public static final int CHANNEL_MODE_STEREO = 2; // 0x2 + field public static final int CHANNEL_COUNT_1 = 1; // 0x1 + field public static final int CHANNEL_COUNT_2 = 2; // 0x2 + field public static final int CHANNEL_COUNT_NONE = 0; // 0x0 field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0 field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240 @@ -952,11 +954,11 @@ package android.bluetooth { field public static final int FRAME_DURATION_10000 = 2; // 0x2 field public static final int FRAME_DURATION_7500 = 1; // 0x1 field public static final int FRAME_DURATION_NONE = 0; // 0x0 - field public static final int SAMPLE_RATE_16000 = 2; // 0x2 - field public static final int SAMPLE_RATE_24000 = 3; // 0x3 - field public static final int SAMPLE_RATE_32000 = 4; // 0x4 - field public static final int SAMPLE_RATE_44100 = 5; // 0x5 - field public static final int SAMPLE_RATE_48000 = 6; // 0x6 + field public static final int SAMPLE_RATE_16000 = 4; // 0x4 + field public static final int SAMPLE_RATE_24000 = 16; // 0x10 + field public static final int SAMPLE_RATE_32000 = 32; // 0x20 + field public static final int SAMPLE_RATE_44100 = 64; // 0x40 + field public static final int SAMPLE_RATE_48000 = 128; // 0x80 field public static final int SAMPLE_RATE_8000 = 1; // 0x1 field public static final int SAMPLE_RATE_NONE = 0; // 0x0 field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240 @@ -968,21 +970,27 @@ package android.bluetooth { ctor public BluetoothLeAudioCodecConfig.Builder(@NonNull android.bluetooth.BluetoothLeAudioCodecConfig); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build(); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setBitsPerSample(int); - method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setChannelMode(int); + method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setChannelCount(int); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecPriority(int); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setFrameDuration(int); + method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setMaxOctetsPerFrame(int); + method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setMinOctetsPerFrame(int); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setOctetsPerFrame(int); method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setSampleRate(int); } public final class BluetoothLeAudioCodecStatus implements android.os.Parcelable { - ctor public BluetoothLeAudioCodecStatus(@Nullable android.bluetooth.BluetoothLeAudioCodecConfig, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>); + ctor public BluetoothLeAudioCodecStatus(@Nullable android.bluetooth.BluetoothLeAudioCodecConfig, @Nullable android.bluetooth.BluetoothLeAudioCodecConfig, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>, @NonNull java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig>); method public int describeContents(); - method @Nullable public android.bluetooth.BluetoothLeAudioCodecConfig getCodecConfig(); - method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getCodecLocalCapabilities(); - method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getCodecSelectableCapabilities(); - method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothLeAudioCodecConfig); + method @Nullable public android.bluetooth.BluetoothLeAudioCodecConfig getInputCodecConfig(); + method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getInputCodecLocalCapabilities(); + method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getInputCodecSelectableCapabilities(); + method @Nullable public android.bluetooth.BluetoothLeAudioCodecConfig getOutputCodecConfig(); + method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getOutputCodecLocalCapabilities(); + method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getOutputCodecSelectableCapabilities(); + method public boolean isInputCodecConfigSelectable(@Nullable android.bluetooth.BluetoothLeAudioCodecConfig); + method public boolean isOutputCodecConfigSelectable(@Nullable android.bluetooth.BluetoothLeAudioCodecConfig); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothLeAudioCodecStatus> CREATOR; field public static final String EXTRA_LE_AUDIO_CODEC_STATUS = "android.bluetooth.extra.LE_AUDIO_CODEC_STATUS"; diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index e29699beed..d5cb46c4f3 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -65,14 +65,14 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis(); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getMostRecentlyConnectedDevices(); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<java.lang.Integer> getSupportedProfiles(); - method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids(); + method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.os.ParcelUuid> getUuidsList(); method public boolean isBleScanAlwaysAvailable(); method public boolean isLeEnabled(); method @NonNull public static String nameForState(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean registerBluetoothConnectionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.BluetoothConnectionCallback); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void requestControllerActivityEnergyInfo(@NonNull android.os.ResultReceiver); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void requestControllerActivityEnergyInfo(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnBluetoothActivityEnergyInfoListener); method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothSocket retrieveConnectedRfcommSocket(@NonNull java.util.UUID); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setDiscoverableTimeout(@NonNull java.time.Duration); @@ -97,6 +97,10 @@ package android.bluetooth { method public void onDeviceDisconnected(@NonNull android.bluetooth.BluetoothDevice, int); } + public static interface BluetoothAdapter.OnBluetoothActivityEnergyInfoListener { + method public void onBluetoothActivityEnergyInfo(@Nullable android.bluetooth.BluetoothActivityEnergyInfo); + } + public static interface BluetoothAdapter.OnMetadataChangedListener { method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]); } @@ -139,7 +143,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int); method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public String getAnonymizedAddress(); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBatteryLevel(); + method @IntRange(from=0xffffff9c, to=100) @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBatteryLevel(); method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public String getIdentityAddress(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getMessageAccessPermission(); method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int); @@ -339,12 +343,12 @@ package android.bluetooth { public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioLocation(@NonNull android.bluetooth.BluetoothDevice); - method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothLeAudioCodecStatus getCodecStatus(@NonNull android.bluetooth.BluetoothDevice); + method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothLeAudioCodecStatus getCodecStatus(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothLeAudio.Callback); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setCodecConfigPreference(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothLeAudioCodecConfig); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setCodecConfigPreference(int, @NonNull android.bluetooth.BluetoothLeAudioCodecConfig, @NonNull android.bluetooth.BluetoothLeAudioCodecConfig); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int); - method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(int); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@IntRange(from=0, to=255) int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull android.bluetooth.BluetoothLeAudio.Callback); field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED = "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED"; field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_LE_AUDIO_GROUP_NODE_STATUS_CHANGED = "android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED"; diff --git a/framework/java/android/bluetooth/BluetoothA2dp.java b/framework/java/android/bluetooth/BluetoothA2dp.java index 8b27e7faef..6c15925d53 100644 --- a/framework/java/android/bluetooth/BluetoothA2dp.java +++ b/framework/java/android/bluetooth/BluetoothA2dp.java @@ -835,9 +835,14 @@ public final class BluetoothA2dp implements BluetoothProfile { } /** - * Enables the optional codecs. + * Enables the optional codecs for the given device for this connection. * - * @param device the remote Bluetooth device. + * If the given device supports another codec type than + * {@link BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC}, this will switch to it. + * See {@link #setOptionalCodecsEnabled} to enable optional codecs by default + * when the given device is connected. + * + * @param device the remote Bluetooth device * @hide */ @SystemApi @@ -851,9 +856,15 @@ public final class BluetoothA2dp implements BluetoothProfile { } /** - * Disables the optional codecs. + * Disables the optional codecs for the given device. * - * @param device the remote Bluetooth device. + * When optional codecs are disabled, the device will use the default + * Bluetooth audio codec type. + * See {@link BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC}. + * See {@link #setOptionalCodecsEnabled} to disable optional codecs by default + * when the given device is connected. + * + * @param device the remote Bluetooth device * @hide */ @SystemApi @@ -870,7 +881,7 @@ public final class BluetoothA2dp implements BluetoothProfile { * Enables or disables the optional codecs. * * @param device the remote Bluetooth device. - * @param enable if true, enable the optional codecs, other disable them + * @param enable if true, enable the optional codecs, otherwise disable them */ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) { @@ -894,17 +905,18 @@ public final class BluetoothA2dp implements BluetoothProfile { /** * Returns whether this device supports optional codecs. * - * @param device The device to check - * @return one of OPTIONAL_CODECS_SUPPORT_UNKNOWN, OPTIONAL_CODECS_NOT_SUPPORTED, or - * OPTIONAL_CODECS_SUPPORTED. + * @param device the remote Bluetooth device + * @return whether the optional codecs are supported or not, or + * {@link #OPTIONAL_CODECS_SUPPORT_UNKNOWN} if the state + * can't be retrieved. * @hide */ @SystemApi @RequiresLegacyBluetoothAdminPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - @OptionalCodecsSupportStatus - public int isOptionalCodecsSupported(@NonNull BluetoothDevice device) { + public @OptionalCodecsSupportStatus int isOptionalCodecsSupported( + @NonNull BluetoothDevice device) { if (DBG) log("isOptionalCodecsSupported(" + device + ")"); verifyDeviceNotNull(device, "isOptionalCodecsSupported"); final IBluetoothA2dp service = getService(); @@ -925,19 +937,20 @@ public final class BluetoothA2dp implements BluetoothProfile { } /** - * Returns whether this device should have optional codecs enabled. + * Returns whether this device has its optional codecs enabled. * - * @param device The device in question. - * @return one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or - * OPTIONAL_CODECS_PREF_DISABLED. + * @param device the remote Bluetooth device + * @return whether the optional codecs are enabled or not, or + * {@link #OPTIONAL_CODECS_PREF_UNKNOWN} if the state + * can't be retrieved. * @hide */ @SystemApi @RequiresLegacyBluetoothAdminPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - @OptionalCodecsPreferenceStatus - public int isOptionalCodecsEnabled(@NonNull BluetoothDevice device) { + public @OptionalCodecsPreferenceStatus int isOptionalCodecsEnabled( + @NonNull BluetoothDevice device) { if (DBG) log("isOptionalCodecsEnabled(" + device + ")"); verifyDeviceNotNull(device, "isOptionalCodecsEnabled"); final IBluetoothA2dp service = getService(); @@ -958,12 +971,13 @@ public final class BluetoothA2dp implements BluetoothProfile { } /** - * Sets a persistent preference for whether a given device should have optional codecs enabled. + * Sets the default state of optional codecs for the given device. + * + * Automatically enables or disables the optional codecs for the given device when + * connected. * - * @param device The device to set this preference for. - * @param value Whether the optional codecs should be enabled for this device. This should be - * one of OPTIONAL_CODECS_PREF_UNKNOWN, OPTIONAL_CODECS_PREF_ENABLED, or - * OPTIONAL_CODECS_PREF_DISABLED. + * @param device the remote Bluetooth device + * @param value whether the optional codecs should be enabled for this device * @hide */ @SystemApi diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index de3f570d96..58ab06dffb 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -59,7 +59,6 @@ import android.os.IBinder; import android.os.IpcDataCache; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.ResultReceiver; import android.sysprop.BluetoothProperties; import android.util.Log; import android.util.Pair; @@ -832,6 +831,55 @@ public final class BluetoothAdapter { }; /** + * Interface for Bluetooth activity energy info listener. Should be implemented by applications + * and set when calling {@link BluetoothAdapter#requestControllerActivityEnergyInfo}. + * + * @hide + */ + @SystemApi + public interface OnBluetoothActivityEnergyInfoListener { + /** + * Called when Bluetooth activity energy info is available. + * Note: this listener is triggered at most once for each call to + * {@link #requestControllerActivityEnergyInfo}. + * + * @param info the latest {@link BluetoothActivityEnergyInfo}, or null if unavailable. + */ + void onBluetoothActivityEnergyInfo(@Nullable BluetoothActivityEnergyInfo info); + } + + private static class OnBluetoothActivityEnergyInfoProxy + extends IBluetoothActivityEnergyInfoListener.Stub { + private final Object mLock = new Object(); + @Nullable @GuardedBy("mLock") private Executor mExecutor; + @Nullable @GuardedBy("mLock") private OnBluetoothActivityEnergyInfoListener mListener; + + OnBluetoothActivityEnergyInfoProxy(Executor executor, + OnBluetoothActivityEnergyInfoListener listener) { + mExecutor = executor; + mListener = listener; + } + + @Override + public void onBluetoothActivityEnergyInfo(BluetoothActivityEnergyInfo info) { + Executor executor; + OnBluetoothActivityEnergyInfoListener listener; + synchronized (mLock) { + if (mExecutor == null || mListener == null) { + return; + } + executor = mExecutor; + listener = mListener; + // null out to allow garbage collection, prevent triggering listener more than once + mExecutor = null; + mListener = null; + } + Binder.clearCallingIdentity(); + executor.execute(() -> listener.onBluetoothActivityEnergyInfo(info)); + } + } + + /** * Get a handle to the default local Bluetooth adapter. * <p> * Currently Android only supports one Bluetooth adapter, but the API could @@ -1488,11 +1536,10 @@ public final class BluetoothAdapter { * @return the UUIDs supported by the local Bluetooth Adapter. * @hide */ - @SystemApi + @UnsupportedAppUsage @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - @SuppressLint(value = {"ArrayReturn", "NullableCollection"}) public @NonNull ParcelUuid[] getUuids() { if (getState() != STATE_ON) { return new ParcelUuid[0]; @@ -1516,6 +1563,18 @@ public final class BluetoothAdapter { } /** + * Get the UUIDs supported by the local Bluetooth adapter. + * + * @return a list of the UUIDs supported by the local Bluetooth Adapter. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) + public @NonNull List<ParcelUuid> getUuidsList() { + return Arrays.asList(getUuids()); + } + + /** * Set the friendly Bluetooth name of the local Bluetooth adapter. * <p>This name is visible to remote Bluetooth devices. * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8 @@ -2675,22 +2734,22 @@ public final class BluetoothAdapter { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, }) - public void requestControllerActivityEnergyInfo(@NonNull ResultReceiver result) { - requireNonNull(result, "ResultReceiver cannot be null"); + public void requestControllerActivityEnergyInfo( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnBluetoothActivityEnergyInfoListener listener) { + requireNonNull(executor, "executor cannot be null"); + requireNonNull(listener, "listener cannot be null"); try { mServiceLock.readLock().lock(); if (mService != null) { - mService.requestActivityInfo(result, mAttributionSource); - result = null; + mService.requestActivityInfo( + new OnBluetoothActivityEnergyInfoProxy(executor, listener), + mAttributionSource); } } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); } finally { mServiceLock.readLock().unlock(); - if (result != null) { - // Only send an immediate result if we failed. - result.send(0, null); - } } } diff --git a/framework/java/android/bluetooth/BluetoothCodecConfig.java b/framework/java/android/bluetooth/BluetoothCodecConfig.java index d0e426853c..16b787db8e 100644 --- a/framework/java/android/bluetooth/BluetoothCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothCodecConfig.java @@ -536,6 +536,8 @@ public final class BluetoothCodecConfig implements Parcelable { /** * Returns the codec specific value1. + * As the value and usage differ for each codec, please refer to the concerned + * codec specification to obtain the codec specific information. */ public long getCodecSpecific1() { return mCodecSpecific1; @@ -543,6 +545,8 @@ public final class BluetoothCodecConfig implements Parcelable { /** * Returns the codec specific value2. + * As the value and usage differ for each codec, please refer to the concerned + * codec specification to obtain the codec specific information. */ public long getCodecSpecific2() { return mCodecSpecific2; @@ -550,6 +554,8 @@ public final class BluetoothCodecConfig implements Parcelable { /** * Returns the codec specific value3. + * As the value and usage differ for each codec, please refer to the concerned + * codec specification to obtain the codec specific information. */ public long getCodecSpecific3() { return mCodecSpecific3; @@ -557,6 +563,8 @@ public final class BluetoothCodecConfig implements Parcelable { /** * Returns the codec specific value4. + * As the value and usage differ for each codec, please refer to the concerned + * codec specification to obtain the codec specific information. */ public long getCodecSpecific4() { return mCodecSpecific4; diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 978c8ed4ac..698e409723 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -19,6 +19,7 @@ package android.bluetooth; import static android.bluetooth.BluetoothUtils.getSyncTimeout; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -794,6 +795,15 @@ public final class BluetoothDevice implements Parcelable, Attributable { /** * Broadcast Action: This intent is used to broadcast CONNECTION ACCESS REQUEST * + * This action will trigger a prompt for the user to accept or deny giving the + * permission for this device. Permissions can be specified with + * {@link #EXTRA_ACCESS_REQUEST_TYPE}. + * + * The reply will be an {@link #ACTION_CONNECTION_ACCESS_REPLY} sent to the specified + * {@link #EXTRA_PACKAGE_NAME} and {@link #EXTRA_CLASS_NAME}. + * + * This action can be cancelled with {@link #ACTION_CONNECTION_ACCESS_CANCEL}. + * * @hide */ @SystemApi @@ -807,6 +817,13 @@ public final class BluetoothDevice implements Parcelable, Attributable { /** * Broadcast Action: This intent is used to broadcast CONNECTION ACCESS REPLY * + * This action is the reply from {@link #ACTION_CONNECTION_ACCESS_REQUEST} + * that is sent to the specified {@link #EXTRA_PACKAGE_NAME} + * and {@link #EXTRA_CLASS_NAME}. + * + * See the extra fields {@link #EXTRA_CONNECTION_ACCESS_RESULT} and + * {@link #EXTRA_ALWAYS_ALLOWED} for possible results. + * * @hide */ @SystemApi @@ -844,7 +861,11 @@ public final class BluetoothDevice implements Parcelable, Attributable { "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; /** - * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent. + * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST}. + * + * Possible values are {@link #REQUEST_TYPE_PROFILE_CONNECTION}, + * {@link #REQUEST_TYPE_PHONEBOOK_ACCESS}, {@link #REQUEST_TYPE_MESSAGE_ACCESS} + * and {@link #REQUEST_TYPE_SIM_ACCESS} * * @hide */ @@ -888,6 +909,8 @@ public final class BluetoothDevice implements Parcelable, Attributable { /** * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent. * + * Possible values are {@link #CONNECTION_ACCESS_YES} and {@link #CONNECTION_ACCESS_NO}. + * * @hide */ @SystemApi @@ -1044,7 +1067,8 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static final int PAIRING_VARIANT_DISPLAY_PIN = 5; /** - * The user will be prompted to accept or deny the OOB pairing request + * The user will be prompted to accept or deny the OOB pairing request. + * This is used for Bluetooth 2.1 secure simple pairing. * * @hide */ @@ -1624,7 +1648,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { @RequiresLegacyBluetoothPermission @RequiresBluetoothConnectPermission @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) - public int getBatteryLevel() { + public @IntRange(from = -100, to = 100) int getBatteryLevel() { if (DBG) log("getBatteryLevel()"); final IBluetooth service = sService; final int defaultValue = BATTERY_LEVEL_BLUETOOTH_OFF; @@ -2009,10 +2033,14 @@ public final class BluetoothDevice implements Parcelable, Attributable { /** * Disconnects all connected bluetooth profiles between the local and remote device. - * Disconnection is asynchronous and you should listen to each profile's broadcast intent + * Disconnection is asynchronous, so you should listen to each profile's broadcast intent * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example, * to verify a2dp is disconnected, you would listen for - * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED} + * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}. Once all profiles have disconnected, + * the ACL link should come down and {@link #ACTION_ACL_DISCONNECTED} should be broadcast. + * <p> + * In the rare event that one or more profiles fail to disconnect, call this method again to + * send another request to disconnect each connected profile. * * @return whether the messages were successfully sent to try to disconnect all profiles * @throws IllegalArgumentException if the device address is invalid diff --git a/framework/java/android/bluetooth/BluetoothDevicePicker.java b/framework/java/android/bluetooth/BluetoothDevicePicker.java index d17ab8d72a..d1fc0622e4 100644 --- a/framework/java/android/bluetooth/BluetoothDevicePicker.java +++ b/framework/java/android/bluetooth/BluetoothDevicePicker.java @@ -30,15 +30,37 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission; */ @SystemApi public interface BluetoothDevicePicker { + + /** + * Extra for filter type used with {@link #ACTION_LAUNCH}. + * The value must be a boolean indicating whether the device should need authentication or not. + */ @SuppressLint("ActionValue") public static final String EXTRA_NEED_AUTH = "android.bluetooth.devicepicker.extra.NEED_AUTH"; + + /** + * Extra for filter type used with {@link #ACTION_LAUNCH}. + * This extra must contain the filter type that will be applied to the device list. + * Possible values are {@link #FILTER_TYPE_ALL}, {@link #FILTER_TYPE_AUDIO}, + * {@link #FILTER_TYPE_TRANSFER}, {@link #FILTER_TYPE_PANU}, and {@link #FILTER_TYPE_NAP}. + */ @SuppressLint("ActionValue") public static final String EXTRA_FILTER_TYPE = "android.bluetooth.devicepicker.extra.FILTER_TYPE"; + + /** + * Extra for filter type used with {@link #ACTION_LAUNCH}. + * This extra must contain the package name that called {@link #ACTION_LAUNCH}. + */ @SuppressLint("ActionValue") public static final String EXTRA_LAUNCH_PACKAGE = "android.bluetooth.devicepicker.extra.LAUNCH_PACKAGE"; + + /** + * Extra for filter type used with {@link #ACTION_LAUNCH}. + * This extra must contain the class name that called {@link #ACTION_LAUNCH}. + */ @SuppressLint("ActionValue") public static final String EXTRA_LAUNCH_CLASS = "android.bluetooth.devicepicker.extra.DEVICE_PICKER_LAUNCH_CLASS"; diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index b81a8a43a0..91b7d499bb 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -22,6 +22,7 @@ import static android.bluetooth.BluetoothUtils.getSyncTimeout; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -152,7 +153,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** * Intent used to broadcast group node status information. * - * <p>This intent will have 3 extra: + * <p>This intent will have 3 extras: * <ul> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can * be null if no device is active. </li> @@ -174,7 +175,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** * Intent used to broadcast group status information. * - * <p>This intent will have 4 extra: + * <p>This intent will have 3 extras: * <ul> * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can * be null if no device is active. </li> @@ -827,13 +828,13 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { } /** - * Get lead device for a group. + * Get Lead device for the group. * * Lead device is the device that can be used as an active device in the system. * Active devices points to the Audio Device for the Le Audio group. - * This method returns a list of Lead devices for all the connected LE Audio - * groups and those devices should be used in the setActiveDevice() method by other parts - * of the system, which wants to setActive a particular Le Audio Group. + * This method returns the Lead devices for the connected LE Audio + * group and this device should be used in the setActiveDevice() method by other parts + * of the system, which wants to set to active a particular Le Audio group. * * Note: getActiveDevice() returns the Lead device for the currently active LE Audio group. * Note: When lead device gets disconnected, there will be new lead device for the group. @@ -1161,7 +1162,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED }) - public void setVolume(int volume) { + public void setVolume(@IntRange(from = 0, to = 255) int volume) { if (VDBG) log("setVolume(vol: " + volume + " )"); final IBluetoothLeAudio service = getService(); if (service == null) { @@ -1392,7 +1393,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** * Gets the current codec status (configuration and capability). * - * @param device the remote Bluetooth device. + * @param groupId The group id * @return the current codec status * @hide */ @@ -1403,9 +1404,9 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED }) - public BluetoothLeAudioCodecStatus getCodecStatus(@NonNull BluetoothDevice device) { + public BluetoothLeAudioCodecStatus getCodecStatus(int groupId) { if (DBG) { - Log.d(TAG, "getCodecStatus(" + device + ")"); + Log.d(TAG, "getCodecStatus(" + groupId + ")"); } final IBluetoothLeAudio service = getService(); @@ -1414,11 +1415,11 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { if (service == null) { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { + } else if (mAdapter.isEnabled()) { try { final SynchronousResultReceiver<BluetoothLeAudioCodecStatus> recv = new SynchronousResultReceiver(); - service.getCodecStatus(device, mAttributionSource, recv); + service.getCodecStatus(groupId, mAttributionSource, recv); return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue); } catch (TimeoutException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); @@ -1433,9 +1434,11 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { /** * Sets the codec configuration preference. * - * @param device the remote Bluetooth device. - * @param codecConfig the codec configuration preference + * @param groupId the groupId + * @param inputCodecConfig the input codec configuration preference + * @param outputCodecConfig the output codec configuration preference * @throws IllegalStateException if LE Audio Service is null + * @throws NullPointerException if any of the configs is null * @hide */ @SystemApi @@ -1444,14 +1447,13 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED }) - public void setCodecConfigPreference(@NonNull BluetoothDevice device, - @NonNull BluetoothLeAudioCodecConfig codecConfig) { - if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")"); + public void setCodecConfigPreference(int groupId, + @NonNull BluetoothLeAudioCodecConfig inputCodecConfig, + @NonNull BluetoothLeAudioCodecConfig outputCodecConfig) { + if (DBG) Log.d(TAG, "setCodecConfigPreference(" + groupId + ")"); - if (codecConfig == null) { - Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); - throw new IllegalArgumentException("codecConfig cannot be null"); - } + Objects.requireNonNull(inputCodecConfig, " inputCodecConfig shall not be null"); + Objects.requireNonNull(outputCodecConfig, " outputCodecConfig shall not be null"); final IBluetoothLeAudio service = getService(); @@ -1459,9 +1461,10 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { Log.w(TAG, "Proxy not attached to service"); if (DBG) log(Log.getStackTraceString(new Throwable())); throw new IllegalStateException("Service is unavailable"); - } else if (mAdapter.isEnabled() && isValidDevice(device)) { + } else if (mAdapter.isEnabled()) { try { - service.setCodecConfigPreference(device, codecConfig, mAttributionSource); + service.setCodecConfigPreference(groupId, inputCodecConfig, outputCodecConfig, + mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); e.rethrowFromSystemServer(); diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java index 004bf6b84f..c91d13ffe0 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecConfig.java @@ -72,7 +72,7 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000; /** @hide */ - @IntDef(prefix = "SAMPLE_RATE_", + @IntDef(flag = true, prefix = "SAMPLE_RATE_", value = {SAMPLE_RATE_NONE, SAMPLE_RATE_8000, SAMPLE_RATE_16000, SAMPLE_RATE_24000, SAMPLE_RATE_32000, SAMPLE_RATE_44100, SAMPLE_RATE_48000}) @Retention(RetentionPolicy.SOURCE) @@ -81,41 +81,45 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { /** * Codec sample rate 0 Hz. Default value used for * codec sample rate. + * Values are the bit mask as defined in the + * Bluetooth Assigned Numbers, Generic Audio, + * Supported_Sampling_Frequencies table + * Note: We use only part of it. */ public static final int SAMPLE_RATE_NONE = 0; /** * Codec sample rate 8000 Hz. */ - public static final int SAMPLE_RATE_8000 = 1; + public static final int SAMPLE_RATE_8000 = 0x01 << 0; /** * Codec sample rate 16000 Hz. */ - public static final int SAMPLE_RATE_16000 = 2; + public static final int SAMPLE_RATE_16000 = 0x01 << 2; /** * Codec sample rate 24000 Hz. */ - public static final int SAMPLE_RATE_24000 = 3; + public static final int SAMPLE_RATE_24000 = 0x01 << 4; /** * Codec sample rate 32000 Hz. */ - public static final int SAMPLE_RATE_32000 = 4; + public static final int SAMPLE_RATE_32000 = 0x01 << 5; /** * Codec sample rate 44100 Hz. */ - public static final int SAMPLE_RATE_44100 = 5; + public static final int SAMPLE_RATE_44100 = 0x01 << 6; /** * Codec sample rate 48000 Hz. */ - public static final int SAMPLE_RATE_48000 = 6; + public static final int SAMPLE_RATE_48000 = 0x01 << 7; /** @hide */ - @IntDef(prefix = "BITS_PER_SAMPLE_", + @IntDef(flag = true, prefix = "BITS_PER_SAMPLE_", value = {BITS_PER_SAMPLE_NONE, BITS_PER_SAMPLE_16, BITS_PER_SAMPLE_24, BITS_PER_SAMPLE_32}) @Retention(RetentionPolicy.SOURCE) @@ -130,42 +134,52 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { /** * Codec bits per sample 16. */ - public static final int BITS_PER_SAMPLE_16 = 1; + public static final int BITS_PER_SAMPLE_16 = 0x01 << 0; /** * Codec bits per sample 24. */ - public static final int BITS_PER_SAMPLE_24 = 2; + public static final int BITS_PER_SAMPLE_24 = 0x01 << 1; /** * Codec bits per sample 32. */ - public static final int BITS_PER_SAMPLE_32 = 3; + public static final int BITS_PER_SAMPLE_32 = 0x01 << 3; - /** @hide */ - @IntDef(prefix = "CHANNEL_MODE_", - value = {CHANNEL_MODE_NONE, CHANNEL_MODE_MONO, CHANNEL_MODE_STEREO}) + /** + * Values are the bit mask as defined in the + * Bluetooth Assigned Numbers, Generic Audio, + * Supported_Audio_Channel_Counts table + * Note: We use only part of it. + * @hide */ + @IntDef(flag = true, prefix = "CHANNEL_COUNT_", + value = {CHANNEL_COUNT_NONE, CHANNEL_COUNT_1, CHANNEL_COUNT_2}) @Retention(RetentionPolicy.SOURCE) - public @interface ChannelMode {} + public @interface ChannelCount {} /** * Codec channel mode NONE. Default value of the * codec channel mode. */ - public static final int CHANNEL_MODE_NONE = 0; + public static final int CHANNEL_COUNT_NONE = 0; /** * Codec channel mode MONO. */ - public static final int CHANNEL_MODE_MONO = 1; + public static final int CHANNEL_COUNT_1 = 0x01 << 0; /** * Codec channel mode STEREO. */ - public static final int CHANNEL_MODE_STEREO = 2; + public static final int CHANNEL_COUNT_2 = 0x01 << 1; - /** @hide */ - @IntDef(prefix = "FRAME_DURATION_", + /** + * Values are the bit mask as defined in the + * Bluetooth Assigned Numbers, Generic Audio, + * Supported_Frame_Durations table + * + * @hide */ + @IntDef(flag = true, prefix = "FRAME_DURATION_", value = {FRAME_DURATION_NONE, FRAME_DURATION_7500, FRAME_DURATION_10000}) @Retention(RetentionPolicy.SOURCE) public @interface FrameDuration {} @@ -178,20 +192,23 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { /** * Frame duration 7500 us. */ - public static final int FRAME_DURATION_7500 = 1; + public static final int FRAME_DURATION_7500 = 0x01 << 0; /** * Frame duration 10000 us. */ - public static final int FRAME_DURATION_10000 = 2; + public static final int FRAME_DURATION_10000 = 0x01 << 1; private final @SourceCodecType int mCodecType; private final @CodecPriority int mCodecPriority; private final @SampleRate int mSampleRate; private final @BitsPerSample int mBitsPerSample; - private final @ChannelMode int mChannelMode; + private final @ChannelCount int mChannelCount; private final @FrameDuration int mFrameDuration; private final int mOctetsPerFrame; + private final int mMinOctetsPerFrame; + private final int mMaxOctetsPerFrame; + /** * Creates a new BluetoothLeAudioCodecConfig. @@ -200,21 +217,26 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { * @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 channelCount the channel count of this codec * @param frameDuration the frame duration of this codec * @param octetsPerFrame the octets per frame of this codec + * @param minOctetsPerFrame the minimum octets per frame of this codec + * @param maxOctetsPerFrame the maximum octets per frame of this codec */ private BluetoothLeAudioCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority, @SampleRate int sampleRate, - @BitsPerSample int bitsPerSample, @ChannelMode int channelMode, - @FrameDuration int frameDuration, int octetsPerFrame) { + @BitsPerSample int bitsPerSample, @ChannelCount int channelCount, + @FrameDuration int frameDuration, int octetsPerFrame, + int minOctetsPerFrame, int maxOctetsPerFrame) { mCodecType = codecType; mCodecPriority = codecPriority; mSampleRate = sampleRate; mBitsPerSample = bitsPerSample; - mChannelMode = channelMode; + mChannelCount = channelCount; mFrameDuration = frameDuration; mOctetsPerFrame = octetsPerFrame; + mMinOctetsPerFrame = minOctetsPerFrame; + mMaxOctetsPerFrame = maxOctetsPerFrame; } @Override @@ -233,11 +255,14 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { int codecPriority = in.readInt(); int sampleRate = in.readInt(); int bitsPerSample = in.readInt(); - int channelMode = in.readInt(); + int channelCount = in.readInt(); int frameDuration = in.readInt(); int octetsPerFrame = in.readInt(); + int minOctetsPerFrame = in.readInt(); + int maxOctetsPerFrame = in.readInt(); return new BluetoothLeAudioCodecConfig(codecType, codecPriority, sampleRate, - bitsPerSample, channelMode, frameDuration, octetsPerFrame); + bitsPerSample, channelCount, frameDuration, octetsPerFrame, + minOctetsPerFrame, maxOctetsPerFrame); } public BluetoothLeAudioCodecConfig[] newArray(int size) { @@ -251,17 +276,21 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { out.writeInt(mCodecPriority); out.writeInt(mSampleRate); out.writeInt(mBitsPerSample); - out.writeInt(mChannelMode); + out.writeInt(mChannelCount); out.writeInt(mFrameDuration); out.writeInt(mOctetsPerFrame); + out.writeInt(mMinOctetsPerFrame); + out.writeInt(mMaxOctetsPerFrame); } @Override public String toString() { return "{codecName:" + getCodecName() + ",mCodecType:" + mCodecType + ",mCodecPriority:" + mCodecPriority + ",mSampleRate:" + mSampleRate - + ",mBitsPerSample:" + mBitsPerSample + ",mChannelMode:" + mChannelMode - + ",mFrameDuration:" + mFrameDuration + ",mOctetsPerFrame:" + mOctetsPerFrame + "}"; + + ",mBitsPerSample:" + mBitsPerSample + ",mChannelCount:" + mChannelCount + + ",mFrameDuration:" + mFrameDuration + ",mOctetsPerFrame:" + mOctetsPerFrame + + ",mMinOctetsPerFrame:" + mMinOctetsPerFrame + + ",mMaxOctetsPerFrame:" + mMaxOctetsPerFrame + "}"; } /** @@ -316,8 +345,8 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { /** * Returns the codec channel mode. */ - public @ChannelMode int getChannelMode() { - return mChannelMode; + public @ChannelCount int getChannelCount() { + return mChannelCount; } /** @@ -334,6 +363,20 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { return mOctetsPerFrame; } + /** + * Returns the minimum octets per frame + */ + public int getMinOctetsPerFrame() { + return mMinOctetsPerFrame; + } + + /** + * Returns the maximum octets per frame + */ + public int getMaxOctetsPerFrame() { + return mMaxOctetsPerFrame; + } + @Override public boolean equals(@NonNull Object o) { if (o instanceof BluetoothLeAudioCodecConfig) { @@ -342,9 +385,11 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { && other.getCodecPriority() == mCodecPriority && other.getSampleRate() == mSampleRate && other.getBitsPerSample() == mBitsPerSample - && other.getChannelMode() == mChannelMode + && other.getChannelCount() == mChannelCount && other.getFrameDuration() == mFrameDuration - && other.getOctetsPerFrame() == mOctetsPerFrame); + && other.getOctetsPerFrame() == mOctetsPerFrame + && other.getMinOctetsPerFrame() == mMinOctetsPerFrame + && other.getMaxOctetsPerFrame() == mMaxOctetsPerFrame); } return false; } @@ -356,7 +401,8 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { @Override public int hashCode() { return Objects.hash(mCodecType, mCodecPriority, mSampleRate, - mBitsPerSample, mChannelMode, mFrameDuration, mOctetsPerFrame); + mBitsPerSample, mChannelCount, mFrameDuration, mOctetsPerFrame, + mMinOctetsPerFrame, mMaxOctetsPerFrame); } /** @@ -369,9 +415,11 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { private int mCodecPriority = BluetoothLeAudioCodecConfig.CODEC_PRIORITY_DEFAULT; private int mSampleRate = BluetoothLeAudioCodecConfig.SAMPLE_RATE_NONE; private int mBitsPerSample = BluetoothLeAudioCodecConfig.BITS_PER_SAMPLE_NONE; - private int mChannelMode = BluetoothLeAudioCodecConfig.CHANNEL_MODE_NONE; + private int mChannelCount = BluetoothLeAudioCodecConfig.CHANNEL_COUNT_NONE; private int mFrameDuration = BluetoothLeAudioCodecConfig.FRAME_DURATION_NONE; private int mOctetsPerFrame = 0; + private int mMinOctetsPerFrame = 0; + private int mMaxOctetsPerFrame = 0; public Builder() {} @@ -380,9 +428,11 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { mCodecPriority = config.getCodecPriority(); mSampleRate = config.getSampleRate(); mBitsPerSample = config.getBitsPerSample(); - mChannelMode = config.getChannelMode(); + mChannelCount = config.getChannelCount(); mFrameDuration = config.getFrameDuration(); mOctetsPerFrame = config.getOctetsPerFrame(); + mMinOctetsPerFrame = config.getMinOctetsPerFrame(); + mMaxOctetsPerFrame = config.getMaxOctetsPerFrame(); } /** @@ -430,13 +480,13 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { } /** - * Set the channel mode for Bluetooth LE audio codec config. + * Set the channel count for Bluetooth LE audio codec config. * - * @param channelMode of this codec + * @param channelCount of this codec * @return the same Builder instance */ - public @NonNull Builder setChannelMode(@ChannelMode int channelMode) { - mChannelMode = channelMode; + public @NonNull Builder setChannelCount(@ChannelCount int channelCount) { + mChannelCount = channelCount; return this; } @@ -463,12 +513,35 @@ public final class BluetoothLeAudioCodecConfig implements Parcelable { } /** + * Set the minimum octets per frame for Bluetooth LE audio codec config. + * + * @param minOctetsPerFrame of this codec + * @return the same Builder instance + */ + public @NonNull Builder setMinOctetsPerFrame(int minOctetsPerFrame) { + mMinOctetsPerFrame = minOctetsPerFrame; + return this; + } + + /** + * Set the maximum octets per frame for Bluetooth LE audio codec config. + * + * @param maxOctetsPerFrame of this codec + * @return the same Builder instance + */ + public @NonNull Builder setMaxOctetsPerFrame(int maxOctetsPerFrame) { + mMaxOctetsPerFrame = maxOctetsPerFrame; + return this; + } + + /** * Build {@link BluetoothLeAudioCodecConfig}. * @return new BluetoothLeAudioCodecConfig built */ public @NonNull BluetoothLeAudioCodecConfig build() { return new BluetoothLeAudioCodecConfig(mCodecType, mCodecPriority, mSampleRate, - mBitsPerSample, mChannelMode, mFrameDuration, mOctetsPerFrame); + mBitsPerSample, mChannelCount, mFrameDuration, mOctetsPerFrame, + mMinOctetsPerFrame, mMaxOctetsPerFrame); } } } diff --git a/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java b/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java index 399ffa743c..bdb9d5d5c6 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java +++ b/framework/java/android/bluetooth/BluetoothLeAudioCodecStatus.java @@ -41,29 +41,47 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { public static final String EXTRA_LE_AUDIO_CODEC_STATUS = "android.bluetooth.extra.LE_AUDIO_CODEC_STATUS"; - private final @Nullable BluetoothLeAudioCodecConfig mCodecConfig; - private final @Nullable List<BluetoothLeAudioCodecConfig> mCodecsLocalCapabilities; - private final @Nullable List<BluetoothLeAudioCodecConfig> mCodecsSelectableCapabilities; + private final @Nullable BluetoothLeAudioCodecConfig mInputCodecConfig; + private final @Nullable BluetoothLeAudioCodecConfig mOutputCodecConfig; + private final @Nullable List<BluetoothLeAudioCodecConfig> mInputCodecsLocalCapabilities; + private final @Nullable List<BluetoothLeAudioCodecConfig> mOutputCodecsLocalCapabilities; + private final @Nullable List<BluetoothLeAudioCodecConfig> mInputCodecsSelectableCapabilities; + private final @Nullable List<BluetoothLeAudioCodecConfig> mOutputCodecsSelectableCapabilities; /** * Represents the codec status for a Bluetooth LE Audio source device. * - * @param codecConfig the current code configutration. - * @param codecsLocalCapabilities the local codecs capabilities. - * @param codecsSelectableCapabilities the selectable codecs capabilities. + * @param inputCodecConfig the current input code configutration. + * @param outputCodecConfig the current output code configutration. + * @param inputCodecsLocalCapabilities the local input codecs capabilities. + * @param outputCodecsLocalCapabilities the local output codecs capabilities. + * @param inputCodecsSelectableCapabilities the selectable input codecs capabilities. + * @param outputCodecsSelectableCapabilities the selectable output codecs capabilities. */ - public BluetoothLeAudioCodecStatus(@Nullable BluetoothLeAudioCodecConfig codecConfig, - @NonNull List<BluetoothLeAudioCodecConfig> codecsLocalCapabilities, - @NonNull List<BluetoothLeAudioCodecConfig> codecsSelectableCapabilities) { - mCodecConfig = codecConfig; - mCodecsLocalCapabilities = codecsLocalCapabilities; - mCodecsSelectableCapabilities = codecsSelectableCapabilities; + public BluetoothLeAudioCodecStatus(@Nullable BluetoothLeAudioCodecConfig inputCodecConfig, + @Nullable BluetoothLeAudioCodecConfig outputCodecConfig, + @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsLocalCapabilities, + @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsLocalCapabilities, + @NonNull List<BluetoothLeAudioCodecConfig> inputCodecsSelectableCapabilities, + @NonNull List<BluetoothLeAudioCodecConfig> outputCodecsSelectableCapabilities) { + mInputCodecConfig = inputCodecConfig; + mOutputCodecConfig = outputCodecConfig; + mInputCodecsLocalCapabilities = inputCodecsLocalCapabilities; + mOutputCodecsLocalCapabilities = outputCodecsLocalCapabilities; + mInputCodecsSelectableCapabilities = inputCodecsSelectableCapabilities; + mOutputCodecsSelectableCapabilities = outputCodecsSelectableCapabilities; } private BluetoothLeAudioCodecStatus(Parcel in) { - mCodecConfig = in.readTypedObject(BluetoothLeAudioCodecConfig.CREATOR); - mCodecsLocalCapabilities = in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR); - mCodecsSelectableCapabilities = + mInputCodecConfig = in.readTypedObject(BluetoothLeAudioCodecConfig.CREATOR); + mOutputCodecConfig = in.readTypedObject(BluetoothLeAudioCodecConfig.CREATOR); + mInputCodecsLocalCapabilities = + in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR); + mOutputCodecsLocalCapabilities = + in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR); + mInputCodecsSelectableCapabilities = + in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR); + mOutputCodecsSelectableCapabilities = in.createTypedArrayList(BluetoothLeAudioCodecConfig.CREATOR); } @@ -71,10 +89,16 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { public boolean equals(@Nullable Object o) { if (o instanceof BluetoothLeAudioCodecStatus) { BluetoothLeAudioCodecStatus other = (BluetoothLeAudioCodecStatus) o; - return (Objects.equals(other.mCodecConfig, mCodecConfig) - && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities) - && sameCapabilities(other.mCodecsSelectableCapabilities, - mCodecsSelectableCapabilities)); + return (Objects.equals(other.mInputCodecConfig, mInputCodecConfig) + && Objects.equals(other.mOutputCodecConfig, mOutputCodecConfig) + && sameCapabilities(other.mInputCodecsLocalCapabilities, + mInputCodecsLocalCapabilities) + && sameCapabilities(other.mOutputCodecsLocalCapabilities, + mOutputCodecsLocalCapabilities) + && sameCapabilities(other.mInputCodecsSelectableCapabilities, + mInputCodecsSelectableCapabilities) + && sameCapabilities(other.mOutputCodecsSelectableCapabilities, + mOutputCodecsSelectableCapabilities)); } return false; } @@ -101,19 +125,67 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { return c1.containsAll(c2); } + private boolean isCodecConfigSelectable(BluetoothLeAudioCodecConfig codecConfig, + BluetoothLeAudioCodecConfig selectableConfig) { + if (codecConfig.getCodecType() != selectableConfig.getCodecType()) { + return false; + } + if ((codecConfig.getFrameDuration() != BluetoothLeAudioCodecConfig.FRAME_DURATION_NONE) + && ((codecConfig.getFrameDuration() & selectableConfig.getFrameDuration()) == 0)) { + return false; + } + if ((codecConfig.getChannelCount() != BluetoothLeAudioCodecConfig.CHANNEL_COUNT_NONE) + && ((codecConfig.getChannelCount() & selectableConfig.getChannelCount()) == 0)) { + return false; + } + if ((codecConfig.getSampleRate() != BluetoothLeAudioCodecConfig.SAMPLE_RATE_NONE) + && ((codecConfig.getSampleRate() & selectableConfig.getSampleRate()) == 0)) { + return false; + } + if ((codecConfig.getBitsPerSample() != BluetoothLeAudioCodecConfig.BITS_PER_SAMPLE_NONE) + && ((codecConfig.getBitsPerSample() & selectableConfig.getBitsPerSample()) == 0)) { + return false; + } + if ((codecConfig.getOctetsPerFrame() != 0) + && ((codecConfig.getOctetsPerFrame() < selectableConfig.getMinOctetsPerFrame()) + || (codecConfig.getOctetsPerFrame() > selectableConfig.getMaxOctetsPerFrame()))) { + return false; + } + return true; + } /** - * Checks whether the codec config matches the selectable capabilities. + * Checks whether the Input codec config matches the selectable capabilities. * Any parameters of the codec config with NONE value will be considered a wildcard matching. * * @param codecConfig the codec config to compare against * @return {@code true} if the codec config matches, {@code false} otherwise */ - public boolean isCodecConfigSelectable(@Nullable BluetoothLeAudioCodecConfig codecConfig) { + public boolean isInputCodecConfigSelectable(@Nullable BluetoothLeAudioCodecConfig codecConfig) { if (codecConfig == null) { return false; } - for (BluetoothLeAudioCodecConfig selectableConfig : mCodecsSelectableCapabilities) { - if (codecConfig.equals(selectableConfig)) { + for (BluetoothLeAudioCodecConfig selectableConfig : mInputCodecsSelectableCapabilities) { + if (isCodecConfigSelectable(codecConfig, selectableConfig)) { + return true; + } + } + return false; + } + + /** + * Checks whether the Output codec config matches the selectable capabilities. + * Any parameters of the codec config with NONE value will be considered a wildcard matching. + * + * @param codecConfig the codec config to compare against + * @return {@code true} if the codec config matches, {@code false} otherwise + */ + public boolean isOutputCodecConfigSelectable( + @Nullable BluetoothLeAudioCodecConfig codecConfig) { + if (codecConfig == null) { + return false; + } + for (BluetoothLeAudioCodecConfig selectableConfig : mOutputCodecsSelectableCapabilities) { + if (isCodecConfigSelectable(codecConfig, selectableConfig)) { return true; } } @@ -125,7 +197,9 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { */ @Override public int hashCode() { - return Objects.hash(mCodecConfig, mCodecsLocalCapabilities, mCodecsLocalCapabilities); + return Objects.hash(mInputCodecConfig, mOutputCodecConfig, + mInputCodecsLocalCapabilities, mOutputCodecsLocalCapabilities, + mInputCodecsSelectableCapabilities, mOutputCodecsSelectableCapabilities); } /** @@ -134,9 +208,12 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { */ @Override public String toString() { - return "{mCodecConfig:" + mCodecConfig - + ",mCodecsLocalCapabilities:" + mCodecsLocalCapabilities - + ",mCodecsSelectableCapabilities:" + mCodecsSelectableCapabilities + return "{mInputCodecConfig:" + mInputCodecConfig + + ",mOutputCodecConfig:" + mOutputCodecConfig + + ",mInputCodecsLocalCapabilities:" + mInputCodecsLocalCapabilities + + ",mOutputCodecsLocalCapabilities:" + mOutputCodecsLocalCapabilities + + ",mInputCodecsSelectableCapabilities:" + mInputCodecsSelectableCapabilities + + ",mOutputCodecsSelectableCapabilities:" + mOutputCodecsSelectableCapabilities + "}"; } @@ -171,38 +248,71 @@ public final class BluetoothLeAudioCodecStatus implements Parcelable { */ @Override public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeTypedObject(mCodecConfig, flags); - out.writeTypedList(mCodecsLocalCapabilities); - out.writeTypedList(mCodecsSelectableCapabilities); + out.writeTypedObject(mInputCodecConfig, flags); + out.writeTypedObject(mOutputCodecConfig, flags); + out.writeTypedList(mInputCodecsLocalCapabilities); + out.writeTypedList(mOutputCodecsLocalCapabilities); + out.writeTypedList(mInputCodecsSelectableCapabilities); + out.writeTypedList(mOutputCodecsSelectableCapabilities); + } + + /** + * Returns the current Input codec configuration. + * + * @return The current input codec config. + */ + public @Nullable BluetoothLeAudioCodecConfig getInputCodecConfig() { + return mInputCodecConfig; } /** - * Returns the current codec configuration. + * Returns the current Output codec configuration. * - * @return The current codec config. + * @return The current output codec config. */ - public @Nullable BluetoothLeAudioCodecConfig getCodecConfig() { - return mCodecConfig; + public @Nullable BluetoothLeAudioCodecConfig getOutputCodecConfig() { + return mOutputCodecConfig; } /** - * Returns the codecs local capabilities. + * Returns the input codecs local capabilities. * * @return The list of codec config that supported by the local system. */ - public @NonNull List<BluetoothLeAudioCodecConfig> getCodecLocalCapabilities() { - return (mCodecsLocalCapabilities == null) - ? Collections.emptyList() : mCodecsLocalCapabilities; + public @NonNull List<BluetoothLeAudioCodecConfig> getInputCodecLocalCapabilities() { + return (mInputCodecsLocalCapabilities == null) + ? Collections.emptyList() : mInputCodecsLocalCapabilities; + } + + /** + * Returns the output codecs local capabilities. + * + * @return The list of codec config that supported by the local system. + */ + public @NonNull List<BluetoothLeAudioCodecConfig> getOutputCodecLocalCapabilities() { + return (mOutputCodecsLocalCapabilities == null) + ? Collections.emptyList() : mOutputCodecsLocalCapabilities; + } + + /** + * Returns the Input codecs selectable capabilities. + * + * @return The list of codec config that supported by both of the local system and + * remote devices. + */ + public @NonNull List<BluetoothLeAudioCodecConfig> getInputCodecSelectableCapabilities() { + return (mInputCodecsSelectableCapabilities == null) + ? Collections.emptyList() : mInputCodecsSelectableCapabilities; } /** - * Returns the codecs selectable capabilities. + * Returns the Output codecs selectable capabilities. * * @return The list of codec config that supported by both of the local system and * remote devices. */ - public @NonNull List<BluetoothLeAudioCodecConfig> getCodecSelectableCapabilities() { - return (mCodecsSelectableCapabilities == null) - ? Collections.emptyList() : mCodecsSelectableCapabilities; + public @NonNull List<BluetoothLeAudioCodecConfig> getOutputCodecSelectableCapabilities() { + return (mOutputCodecsSelectableCapabilities == null) + ? Collections.emptyList() : mOutputCodecsSelectableCapabilities; } } diff --git a/system/binder/Android.bp b/system/binder/Android.bp index c5b0a61e99..475f91d25c 100644 --- a/system/binder/Android.bp +++ b/system/binder/Android.bp @@ -20,6 +20,7 @@ filegroup { "android/bluetooth/IBluetooth.aidl", "android/bluetooth/IBluetoothA2dp.aidl", "android/bluetooth/IBluetoothA2dpSink.aidl", + "android/bluetooth/IBluetoothActivityEnergyInfoListener.aidl", "android/bluetooth/IBluetoothAvrcpController.aidl", "android/bluetooth/IBluetoothAvrcpTarget.aidl", "android/bluetooth/IBluetoothBattery.aidl", diff --git a/system/binder/android/bluetooth/IBluetooth.aidl b/system/binder/android/bluetooth/IBluetooth.aidl index 369f7e5410..2404e81031 100644 --- a/system/binder/android/bluetooth/IBluetooth.aidl +++ b/system/binder/android/bluetooth/IBluetooth.aidl @@ -17,6 +17,7 @@ package android.bluetooth; import android.app.PendingIntent; +import android.bluetooth.IBluetoothActivityEnergyInfoListener; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothConnectionCallback; import android.bluetooth.IBluetoothMetadataListener; @@ -231,7 +232,7 @@ interface IBluetooth * The result code is ignored. */ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") - oneway void requestActivityInfo(in ResultReceiver result, in AttributionSource attributionSource); + oneway void requestActivityInfo(in IBluetoothActivityEnergyInfoListener listener, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") oneway void onLeServiceUp(in AttributionSource attributionSource, in SynchronousResultReceiver receiver); diff --git a/system/binder/android/bluetooth/IBluetoothActivityEnergyInfoListener.aidl b/system/binder/android/bluetooth/IBluetoothActivityEnergyInfoListener.aidl new file mode 100644 index 0000000000..24ae14adb9 --- /dev/null +++ b/system/binder/android/bluetooth/IBluetoothActivityEnergyInfoListener.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 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.bluetooth.BluetoothActivityEnergyInfo; + +/** + * Interface for Bluetooth activity energy info listener. + * + * {@hide} + */ +oneway interface IBluetoothActivityEnergyInfoListener +{ + /** + * AdapterService to BluetoothAdapter callback providing current Bluetooth + * activity energy info. + * @param info the Bluetooth activity energy info + */ + void onBluetoothActivityEnergyInfo(in BluetoothActivityEnergyInfo info); +}
\ No newline at end of file diff --git a/system/binder/android/bluetooth/IBluetoothLeAudio.aidl b/system/binder/android/bluetooth/IBluetoothLeAudio.aidl index 7039c744ae..7a3a05a739 100644 --- a/system/binder/android/bluetooth/IBluetoothLeAudio.aidl +++ b/system/binder/android/bluetooth/IBluetoothLeAudio.aidl @@ -54,9 +54,9 @@ oneway interface IBluetoothLeAudio { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") void getConnectedGroupLeadDevice(int groupId, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - void getCodecStatus(in BluetoothDevice device, in AttributionSource source, in SynchronousResultReceiver receiver); + void getCodecStatus(in int groupId, in AttributionSource source, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - void setCodecConfigPreference(in BluetoothDevice device, in BluetoothLeAudioCodecConfig codecConfig, in AttributionSource source); + void setCodecConfigPreference(in int groupId, in BluetoothLeAudioCodecConfig inputCodecConfig, in BluetoothLeAudioCodecConfig outputCodecConfig, in AttributionSource source); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") void registerCallback(in IBluetoothLeAudioCallback callback, in AttributionSource attributionSource, in SynchronousResultReceiver receiver); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc index 1ab4ca5592..bf385f8617 100644 --- a/system/bta/dm/bta_dm_act.cc +++ b/system/bta/dm/bta_dm_act.cc @@ -3100,7 +3100,7 @@ static void bta_dm_set_eir(char* local_name) { if (free_eir_length) UINT8_TO_STREAM(p, 0); /* terminator of significant part */ - BTM_WriteEIR(p_buf); + get_btm_client_interface().eir.BTM_WriteEIR(p_buf); } #if (BTA_EIR_CANNED_UUID_LIST != TRUE) diff --git a/system/bta/include/bta_api.h b/system/bta/include/bta_api.h index 3c0bd4b38a..b3049c80ac 100644 --- a/system/bta/include/bta_api.h +++ b/system/bta/include/bta_api.h @@ -775,7 +775,7 @@ tBTA_STATUS BTA_DmGetCachedRemoteName(const RawAddress& remote_device, * ******************************************************************************/ extern void BTA_DmBond(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type, - tBT_TRANSPORT transport, tBLE_ADDR_TYPE device_type); + tBT_TRANSPORT transport, tBT_DEVICE_TYPE device_type); /******************************************************************************* * diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc index c063873af9..5fa4e5a94b 100644 --- a/system/bta/le_audio/state_machine_test.cc +++ b/system/bta/le_audio/state_machine_test.cc @@ -173,7 +173,7 @@ class StateMachineTest : public Test { : ((uint16_t)(remote_bda.address[0] ^ remote_bda.address[1] ^ remote_bda.address[2])) - << 8 || + << 8 | (remote_bda.address[3] ^ remote_bda.address[4] ^ remote_bda.address[5]); })); diff --git a/system/main/Android.bp b/system/main/Android.bp index b8aa2955ef..8a147b3177 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -101,7 +101,7 @@ cc_library { "-DBUILDCFG", ], sanitize: { - never: true, + scs: true, }, host_supported: true, min_sdk_version: "30", diff --git a/system/main/shim/btm_api.cc b/system/main/shim/btm_api.cc index d5f3023c4e..646a67cab0 100644 --- a/system/main/shim/btm_api.cc +++ b/system/main/shim/btm_api.cc @@ -878,13 +878,6 @@ tBTM_STATUS bluetooth::shim::BTM_ClearInqDb(const RawAddress* p_bda) { return BTM_NO_RESOURCES; } -tBTM_STATUS bluetooth::shim::BTM_WriteEIR(BT_HDR* p_buff) { - LOG_INFO("UNIMPLEMENTED %s", __func__); - CHECK(p_buff != nullptr); - osi_free(p_buff); - return BTM_NO_RESOURCES; -} - bool bluetooth::shim::BTM_HasEirService(const uint32_t* p_eir_uuid, uint16_t uuid16) { LOG_INFO("UNIMPLEMENTED %s", __func__); diff --git a/system/main/shim/btm_api.h b/system/main/shim/btm_api.h index 65bcc60a8e..93f261ee5c 100644 --- a/system/main/shim/btm_api.h +++ b/system/main/shim/btm_api.h @@ -289,21 +289,6 @@ tBTM_STATUS BTM_ClearInqDb(const RawAddress* p_bda); /******************************************************************************* * - * Function BTM_WriteEIR - * - * Description This function is called to write EIR data to controller. - * - * Parameters p_buff - allocated HCI command buffer including extended - * inquriry response - * - * Returns BTM_SUCCESS - if successful - * BTM_MODE_UNSUPPORTED - if local device cannot support it - * - ******************************************************************************/ -tBTM_STATUS BTM_WriteEIR(BT_HDR* p_buff); - -/******************************************************************************* - * * Function BTM_HasEirService * * Description This function is called to know if UUID in bit map of UUID. diff --git a/system/main/shim/le_advertising_manager.cc b/system/main/shim/le_advertising_manager.cc index 1267752120..42313689af 100644 --- a/system/main/shim/le_advertising_manager.cc +++ b/system/main/shim/le_advertising_manager.cc @@ -374,5 +374,7 @@ BleAdvertiserInterface* bluetooth::shim::get_ble_advertiser_instance() { }; void bluetooth::shim::init_advertising_manager() { - bt_le_advertiser_instance->Init(); + static_cast<BleAdvertiserInterfaceImpl*>( + bluetooth::shim::get_ble_advertiser_instance()) + ->Init(); } diff --git a/system/test/mock/mock_main_shim_btm_api.cc b/system/test/mock/mock_main_shim_btm_api.cc index a2a13194c4..975374d009 100644 --- a/system/test/mock/mock_main_shim_btm_api.cc +++ b/system/test/mock/mock_main_shim_btm_api.cc @@ -217,10 +217,6 @@ tBTM_STATUS bluetooth::shim::BTM_StartInquiry(tBTM_INQ_RESULTS_CB* p_results_cb, mock_function_count_map[__func__]++; return BTM_SUCCESS; } -tBTM_STATUS bluetooth::shim::BTM_WriteEIR(BT_HDR* p_buff) { - mock_function_count_map[__func__]++; - return BTM_SUCCESS; -} tBTM_STATUS bluetooth::shim::btm_sec_mx_access_request( const RawAddress& bd_addr, bool is_originator, uint16_t security_requirement, tBTM_SEC_CALLBACK* p_callback, diff --git a/system/test/mock/mock_stack_btm.cc b/system/test/mock/mock_stack_btm.cc index 89ef550e5d..d72c821d3d 100644 --- a/system/test/mock/mock_stack_btm.cc +++ b/system/test/mock/mock_stack_btm.cc @@ -30,10 +30,13 @@ void BTM_BleBackgroundObserve(bool enable, tBTM_INQ_RESULTS_CB* p_results_cb) {} void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK* p_vsc_cback) {} uint8_t BTM_GetAcceptlistSize() { return 0; } +tBTM_STATUS BTM_WriteEIR(BT_HDR* p_buff) { return BTM_SUCCESS; } + struct btm_client_interface_t btm_client_interface = { .eir = { .BTM_GetEirSupportedServices = BTM_GetEirSupportedServices, + .BTM_WriteEIR = BTM_WriteEIR, }, }; diff --git a/system/test/mock/mock_stack_btm_inq.cc b/system/test/mock/mock_stack_btm_inq.cc index 1d1c8e25ee..c068026118 100644 --- a/system/test/mock/mock_stack_btm_inq.cc +++ b/system/test/mock/mock_stack_btm_inq.cc @@ -109,10 +109,6 @@ tBTM_STATUS BTM_StartInquiry(tBTM_INQ_RESULTS_CB* p_results_cb, mock_function_count_map[__func__]++; return BTM_SUCCESS; } -tBTM_STATUS BTM_WriteEIR(BT_HDR* p_buff) { - mock_function_count_map[__func__]++; - return BTM_SUCCESS; -} tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda, uint8_t origin, uint64_t timeout_ms, tBTM_CMPL_CB* p_cb) { mock_function_count_map[__func__]++; |