diff options
| -rw-r--r-- | core/jni/android_media_AudioSystem.cpp | 10 | ||||
| -rw-r--r-- | media/java/android/media/AudioSystem.java | 30 | ||||
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 234 |
3 files changed, 207 insertions, 67 deletions
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 80560f826235..860de75787a7 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -487,7 +487,8 @@ android_media_AudioSystem_recording_callback(int event, } static jint -android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name) +android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name, + jint codec __unused) { const char *c_address = env->GetStringUTFChars(device_address, NULL); const char *c_name = env->GetStringUTFChars(device_name, NULL); @@ -510,7 +511,8 @@ android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, ji } static jint -android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name) +android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name, + jint codec __unused) { const char *c_address = env->GetStringUTFChars(device_address, NULL); const char *c_name = env->GetStringUTFChars(device_name, NULL); @@ -2142,9 +2144,9 @@ static const JNINativeMethod gMethods[] = { {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive}, {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId}, {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId}, - {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, + {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, - {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange}, + {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_handleDeviceConfigChange}, {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index de73649d59dc..ddded5f02b48 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -140,6 +140,30 @@ public class AudioSystem } } + /* Formats for A2DP codecs, must match system/audio-base.h audio_format_t */ + public static final int AUDIO_FORMAT_INVALID = 0xFFFFFFFF; + public static final int AUDIO_FORMAT_DEFAULT = 0; + public static final int AUDIO_FORMAT_AAC = 0x04000000; + public static final int AUDIO_FORMAT_SBC = 0x1F000000; + public static final int AUDIO_FORMAT_APTX = 0x20000000; + public static final int AUDIO_FORMAT_APTX_HD = 0x21000000; + public static final int AUDIO_FORMAT_LDAC = 0x23000000; + + /** converts audio format enum to string */ + public static String audioFormatToString(int audioFormat) { + switch (audioFormat) { + case AUDIO_FORMAT_INVALID: return "AUDIO_FORMAT_INVALID"; + case AUDIO_FORMAT_DEFAULT: return "AUDIO_FORMAT_DEFAULT"; + case AUDIO_FORMAT_AAC: return "AUDIO_FORMAT_AAC"; + case AUDIO_FORMAT_SBC: return "AUDIO_FORMAT_SBC"; + case AUDIO_FORMAT_APTX: return "AUDIO_FORMAT_APTX"; + case AUDIO_FORMAT_APTX_HD: return "AUDIO_FORMAT_APTX_HD"; + case AUDIO_FORMAT_LDAC: return "AUDIO_FORMAT_LDAC"; + default: return "unknown audio format (" + audioFormat + ")"; + } + } + + /* Routing bits for the former setRouting/getRouting API */ /** @deprecated */ @Deprecated public static final int ROUTE_EARPIECE = (1 << 0); @@ -860,12 +884,14 @@ public class AudioSystem */ @UnsupportedAppUsage public static native int setDeviceConnectionState(int device, int state, - String device_address, String device_name); + String device_address, String device_name, + int codecFormat); @UnsupportedAppUsage public static native int getDeviceConnectionState(int device, String device_address); public static native int handleDeviceConfigChange(int device, String device_address, - String device_name); + String device_name, + int codecFormat); @UnsupportedAppUsage public static native int setPhoneState(int state); @UnsupportedAppUsage diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 9a4ca1f954d0..1662fce31ff4 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -38,6 +38,8 @@ import android.app.NotificationManager; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothCodecConfig; +import android.bluetooth.BluetoothCodecStatus; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothHearingAid; @@ -480,16 +482,20 @@ public class AudioService extends IAudioService.Stub int mDeviceType; String mDeviceName; String mDeviceAddress; + int mDeviceCodecFormat; - public DeviceListSpec(int deviceType, String deviceName, String deviceAddress) { + DeviceListSpec(int deviceType, String deviceName, String deviceAddress, + int deviceCodecFormat) { mDeviceType = deviceType; mDeviceName = deviceName; mDeviceAddress = deviceAddress; + mDeviceCodecFormat = deviceCodecFormat; } public String toString() { return "[type:0x" + Integer.toHexString(mDeviceType) + " name:" + mDeviceName - + " address:" + mDeviceAddress + "]"; + + " address:" + mDeviceAddress + + " codec: " + Integer.toHexString(mDeviceCodecFormat) + "]"; } } @@ -501,6 +507,52 @@ public class AudioService extends IAudioService.Stub private final ArrayMap<String, DeviceListSpec> mConnectedDevices = new ArrayMap<>(); + private class BluetoothA2dpDeviceInfo { + BluetoothDevice mBtDevice; + int mVolume; + int mCodec; + + BluetoothA2dpDeviceInfo(BluetoothDevice btDevice) { + this(btDevice, -1, AudioSystem.AUDIO_FORMAT_DEFAULT); + } + + BluetoothA2dpDeviceInfo(BluetoothDevice btDevice, + int volume, int codec) { + mBtDevice = btDevice; + mVolume = volume; + mCodec = codec; + } + + public BluetoothDevice getBtDevice() { + return mBtDevice; + } + + public int getVolume() { + return mVolume; + } + + public int getCodec() { + return mCodec; + } + } + + private int mapBluetoothCodecToAudioFormat(int btCodecType) { + switch (btCodecType) { + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC: + return AudioSystem.AUDIO_FORMAT_SBC; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC: + return AudioSystem.AUDIO_FORMAT_AAC; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX: + return AudioSystem.AUDIO_FORMAT_APTX; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD: + return AudioSystem.AUDIO_FORMAT_APTX_HD; + case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC: + return AudioSystem.AUDIO_FORMAT_LDAC; + default: + return AudioSystem.AUDIO_FORMAT_DEFAULT; + } + } + // Forced device usage for communications private int mForcedUseForComm; private int mForcedUseForCommExt; // External state returned by getters: always consistent @@ -1020,7 +1072,8 @@ public class AudioService extends IAudioService.Stub spec.mDeviceType, AudioSystem.DEVICE_STATE_AVAILABLE, spec.mDeviceAddress, - spec.mDeviceName); + spec.mDeviceName, + spec.mDeviceCodecFormat); } } // Restore call state @@ -3904,8 +3957,8 @@ public class AudioService extends IAudioService.Stub queueMsgUnderWakeLock(mAudioHandler, MSG_SET_A2DP_SINK_CONNECTION_STATE, state, - -1, - btDevice, + 0 /* arg2 unused */, + new BluetoothA2dpDeviceInfo(btDevice), delay); } } @@ -3922,7 +3975,7 @@ public class AudioService extends IAudioService.Stub MSG_SET_A2DP_SRC_CONNECTION_STATE, state, 0 /* arg2 unused */, - btDevice, + new BluetoothA2dpDeviceInfo(btDevice), 0 /* delay */); } } @@ -4687,6 +4740,17 @@ public class AudioService extends IAudioService.Stub } } + private int getA2dpCodec(BluetoothDevice device) { + synchronized (mA2dpAvrcpLock) { + if (mA2dp != null) { + BluetoothCodecStatus btCodecStatus = mA2dp.getCodecStatus(device); + BluetoothCodecConfig btCodecConfig = btCodecStatus.getCodecConfig(); + return mapBluetoothCodecToAudioFormat(btCodecConfig.getCodecType()); + } + return AudioSystem.AUDIO_FORMAT_DEFAULT; + } + } + /* * A class just for packaging up a set of connection parameters. */ @@ -4751,14 +4815,16 @@ public class AudioService extends IAudioService.Stub return delay; } - public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile) + public int setBluetoothA2dpDeviceConnectionState( + BluetoothDevice device, int state, int profile) { return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( - device, state, profile, false /* suppressNoisyIntent */, -1 /* a2dpVolume */); + device, state, profile, false /* suppressNoisyIntent */, + -1 /* a2dpVolume */); } public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device, - int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) + int state, int profile, boolean suppressNoisyIntent, int a2dpVolume) { mDeviceLogger.log((new AudioEventLogger.StringEvent( "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent state=" + state @@ -4771,7 +4837,8 @@ public class AudioService extends IAudioService.Stub return 0; } return setBluetoothA2dpDeviceConnectionStateInt( - device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume); + device, state, profile, suppressNoisyIntent, + AudioSystem.DEVICE_NONE, a2dpVolume); } public int setBluetoothA2dpDeviceConnectionStateInt( @@ -4791,18 +4858,20 @@ public class AudioService extends IAudioService.Stub delay = 0; } + int a2dpCodec = getA2dpCodec(device); + if (DEBUG_DEVICES) { Log.d(TAG, "setBluetoothA2dpDeviceConnectionStateInt device: " + device - + " state: " + state + " delay(ms): " + delay - + " suppressNoisyIntent: " + suppressNoisyIntent); + + " state: " + state + " delay(ms): " + delay + "codec:" + a2dpCodec + + " suppressNoisyIntent: " + suppressNoisyIntent); } queueMsgUnderWakeLock(mAudioHandler, (profile == BluetoothProfile.A2DP ? MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), state, - a2dpVolume, - device, + 0, /* arg2 unused */ + new BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec), delay); } return delay; @@ -4811,11 +4880,12 @@ public class AudioService extends IAudioService.Stub public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device) { synchronized (mConnectedDevices) { + int a2dpCodec = getA2dpCodec(device); queueMsgUnderWakeLock(mAudioHandler, MSG_A2DP_DEVICE_CONFIG_CHANGE, 0 /* arg1 unused */, - 0 /* arg1 unused */, - device, + 0 /* arg2 unused */, + new BluetoothA2dpDeviceInfo(device, -1, a2dpCodec), 0 /* delay */); } } @@ -5697,7 +5767,7 @@ public class AudioService extends IAudioService.Stub case MSG_BTA2DP_DOCK_TIMEOUT: // msg.obj == address of BTA2DP device synchronized (mConnectedDevices) { - makeA2dpDeviceUnavailableNow( (String) msg.obj ); + makeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); } mAudioEventWakeLock.release(); break; @@ -5722,12 +5792,12 @@ public class AudioService extends IAudioService.Stub break; case MSG_SET_A2DP_SRC_CONNECTION_STATE: - onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1); + onSetA2dpSourceConnectionState((BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); mAudioEventWakeLock.release(); break; case MSG_SET_A2DP_SINK_CONNECTION_STATE: - onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1, msg.arg2); + onSetA2dpSinkConnectionState((BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); mAudioEventWakeLock.release(); break; @@ -5737,7 +5807,7 @@ public class AudioService extends IAudioService.Stub break; case MSG_A2DP_DEVICE_CONFIG_CHANGE: - onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj); + onBluetoothA2dpDeviceConfigChange((BluetoothA2dpDeviceInfo) msg.obj); mAudioEventWakeLock.release(); break; @@ -5911,19 +5981,20 @@ public class AudioService extends IAudioService.Stub } // must be called synchronized on mConnectedDevices - private void makeA2dpDeviceAvailable(String address, String name, String eventSource) { + private void makeA2dpDeviceAvailable( + String address, String name, String eventSource, int a2dpCodec) { // enable A2DP before notifying A2DP connection to avoid unnecessary processing in // audio policy manager VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; setBluetoothA2dpOnInt(true, eventSource); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_AVAILABLE, address, name); + AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec); // Reset A2DP suspend state each time a new sink is connected AudioSystem.setParameters("A2dpSuspended=false"); mConnectedDevices.put( makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address), new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name, - address)); + address, a2dpCodec)); sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0); setCurrentAudioRouteNameIfPossible(name); @@ -5936,7 +6007,7 @@ public class AudioService extends IAudioService.Stub } // must be called synchronized on mConnectedDevices - private void makeA2dpDeviceUnavailableNow(String address) { + private void makeA2dpDeviceUnavailableNow(String address, int a2dpCodec) { if (address == null) { return; } @@ -5944,7 +6015,7 @@ public class AudioService extends IAudioService.Stub mAvrcpAbsVolSupported = false; } AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, ""); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", a2dpCodec); mConnectedDevices.remove( makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address)); // Remove A2DP routes as well @@ -5959,32 +6030,38 @@ public class AudioService extends IAudioService.Stub // prevent any activity on the A2DP audio output to avoid unwanted // reconnection of the sink. AudioSystem.setParameters("A2dpSuspended=true"); + // Retrieve deviceSpec before removing device + String deviceKey = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address); + DeviceListSpec deviceSpec = mConnectedDevices.get(deviceKey); + int a2dpCodec = deviceSpec != null ? deviceSpec.mDeviceCodecFormat : + AudioSystem.AUDIO_FORMAT_DEFAULT; // the device will be made unavailable later, so consider it disconnected right away - mConnectedDevices.remove( - makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address)); + mConnectedDevices.remove(deviceKey); // send the delayed message to make the device unavailable later queueMsgUnderWakeLock(mAudioHandler, - MSG_BTA2DP_DOCK_TIMEOUT, - 0, - 0, - address, - delayMs); + MSG_BTA2DP_DOCK_TIMEOUT, + a2dpCodec, + 0, + address, + delayMs); } // must be called synchronized on mConnectedDevices private void makeA2dpSrcAvailable(String address) { AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_AVAILABLE, address, ""); + AudioSystem.DEVICE_STATE_AVAILABLE, address, "", + AudioSystem.AUDIO_FORMAT_DEFAULT); mConnectedDevices.put( makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address), new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "", - address)); + address, AudioSystem.AUDIO_FORMAT_DEFAULT)); } // must be called synchronized on mConnectedDevices private void makeA2dpSrcUnavailable(String address) { AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, ""); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", + AudioSystem.AUDIO_FORMAT_DEFAULT); mConnectedDevices.remove( makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address)); } @@ -6008,11 +6085,12 @@ public class AudioService extends IAudioService.Stub setHearingAidVolume(index, AudioSystem.STREAM_MUSIC); AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID, - AudioSystem.DEVICE_STATE_AVAILABLE, address, name); + AudioSystem.DEVICE_STATE_AVAILABLE, address, name, + AudioSystem.AUDIO_FORMAT_DEFAULT); mConnectedDevices.put( makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address), new DeviceListSpec(AudioSystem.DEVICE_OUT_HEARING_AID, name, - address)); + address, AudioSystem.AUDIO_FORMAT_DEFAULT)); sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE, AudioSystem.DEVICE_OUT_HEARING_AID, 0, null, 0); sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, @@ -6024,7 +6102,8 @@ public class AudioService extends IAudioService.Stub // must be called synchronized on mConnectedDevices private void makeHearingAidDeviceUnavailable(String address) { AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, ""); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", + AudioSystem.AUDIO_FORMAT_DEFAULT); mConnectedDevices.remove( makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address)); // Remove Hearing Aid routes as well @@ -6041,15 +6120,23 @@ public class AudioService extends IAudioService.Stub return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); } - private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state, int a2dpVolume) + private void onSetA2dpSinkConnectionState(BluetoothA2dpDeviceInfo btInfo, int state) { - if (DEBUG_DEVICES) { - Log.d(TAG, "onSetA2dpSinkConnectionState btDevice= " + btDevice+" state= " + state - + " is dock: "+btDevice.isBluetoothDock()); + if (btInfo == null) { + return; } + + BluetoothDevice btDevice = btInfo.getBtDevice(); + int a2dpVolume = btInfo.getVolume(); + int a2dpCodec = btInfo.getCodec(); + if (btDevice == null) { return; } + if (DEBUG_DEVICES) { + Log.d(TAG, "onSetA2dpSinkConnectionState btDevice= " + btDevice + " state= " + state + + " is dock: " + btDevice.isBluetoothDock()); + } String address = btDevice.getAddress(); if (!BluetoothAdapter.checkBluetoothAddress(address)) { address = ""; @@ -6071,7 +6158,7 @@ public class AudioService extends IAudioService.Stub // the next time isConnected is evaluated, it will be false for the dock } } else { - makeA2dpDeviceUnavailableNow(address); + makeA2dpDeviceUnavailableNow(address, deviceSpec.mDeviceCodecFormat); } } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { if (btDevice.isBluetoothDock()) { @@ -6083,7 +6170,8 @@ public class AudioService extends IAudioService.Stub // a dock: cancel the dock timeout, and make the dock unavailable now if (hasScheduledA2dpDockTimeout() && mDockAddress != null) { cancelA2dpDeviceTimeout(); - makeA2dpDeviceUnavailableNow(mDockAddress); + makeA2dpDeviceUnavailableNow(mDockAddress, + AudioSystem.AUDIO_FORMAT_DEFAULT); } } if (a2dpVolume != -1) { @@ -6095,13 +6183,18 @@ public class AudioService extends IAudioService.Stub setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); } makeA2dpDeviceAvailable(address, btDevice.getName(), - "onSetA2dpSinkConnectionState"); + "onSetA2dpSinkConnectionState", a2dpCodec); } } } - private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) + private void onSetA2dpSourceConnectionState(BluetoothA2dpDeviceInfo btInfo, int state) { + if (btInfo == null) { + return; + } + BluetoothDevice btDevice = btInfo.getBtDevice(); + if (DEBUG_VOL) { Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state); } @@ -6176,8 +6269,14 @@ public class AudioService extends IAudioService.Stub return false; } - private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice) + private void onBluetoothA2dpDeviceConfigChange(BluetoothA2dpDeviceInfo btInfo) { + if (btInfo == null) { + return; + } + BluetoothDevice btDevice = btInfo.getBtDevice(); + int a2dpCodec = btInfo.getCodec(); + if (DEBUG_DEVICES) { Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice); } @@ -6200,17 +6299,27 @@ public class AudioService extends IAudioService.Stub } final String key = makeDeviceListKey(device, address); final DeviceListSpec deviceSpec = mConnectedDevices.get(key); - if (deviceSpec != null) { - // Device is connected - int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC); - if (AudioSystem.handleDeviceConfigChange(device, address, - btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) { - // force A2DP device disconnection in case of error so that AudioService state is - // consistent with audio policy manager state - setBluetoothA2dpDeviceConnectionStateInt( - btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP, - false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */); - } + if (deviceSpec == null) { + return; + } + // Device is connected + if (deviceSpec.mDeviceCodecFormat != a2dpCodec) { + deviceSpec.mDeviceCodecFormat = a2dpCodec; + mConnectedDevices.replace(key, deviceSpec); + } + if (DEBUG_DEVICES) { + Log.d(TAG, "onBluetoothA2dpDeviceConfigChange: codec=" + + deviceSpec.mDeviceCodecFormat); + } + if (AudioSystem.handleDeviceConfigChange(device, address, + btDevice.getName(), deviceSpec.mDeviceCodecFormat) + != AudioSystem.AUDIO_STATUS_OK) { + int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC); + // force A2DP device disconnection in case of error so that AudioService state is + // consistent with audio policy manager state + setBluetoothA2dpDeviceConnectionStateInt( + btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP, + false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */); } } } @@ -6243,19 +6352,22 @@ public class AudioService extends IAudioService.Stub } if (connect && !isConnected) { final int res = AudioSystem.setDeviceConnectionState(device, - AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName); + AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName, + AudioSystem.AUDIO_FORMAT_DEFAULT); if (res != AudioSystem.AUDIO_STATUS_OK) { Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device) + " due to command error " + res ); return false; } - mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address)); + mConnectedDevices.put(deviceKey, new DeviceListSpec(device, + deviceName, address, AudioSystem.AUDIO_FORMAT_DEFAULT)); sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE, device, 0, null, 0); return true; } else if (!connect && isConnected) { AudioSystem.setDeviceConnectionState(device, - AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName); + AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName, + AudioSystem.AUDIO_FORMAT_DEFAULT); // always remove even if disconnection failed mConnectedDevices.remove(deviceKey); return true; |