diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java index 3bab29fcc27fb..a67ce170a701f 100644 --- a/core/java/android/view/VolumePanel.java +++ b/core/java/android/view/VolumePanel.java @@ -403,7 +403,10 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie case AudioManager.STREAM_MUSIC: { // message = MUSIC_VOLUME_TEXT; // Special case for when Bluetooth is active for music - if (mAudioManager.isBluetoothA2dpOn()) { + if ((mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC) & + (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP | + AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | + AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) { // additionalMessage = // com.android.internal.R.string.volume_music_hint_playing_through_bluetooth; // setLargeIcon(com.android.internal.R.drawable.ic_volume_bluetooth_ad2p); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 5147cfabc66b4..5f3fed2167443 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -192,6 +192,12 @@ android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, jobject thiz, jint s return index; } +static jint +android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream) +{ + return (jint) AudioSystem::getDevicesForStream(static_cast (stream)); +} + // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { @@ -208,7 +214,8 @@ static JNINativeMethod gMethods[] = { {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, {"setStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_setStreamVolumeIndex}, - {"getStreamVolumeIndex","(I)I", (void *)android_media_AudioSystem_getStreamVolumeIndex} + {"getStreamVolumeIndex","(I)I", (void *)android_media_AudioSystem_getStreamVolumeIndex}, + {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, }; const char* const kClassPathName = "android/media/AudioSystem"; diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 03f894404a172..2dc4beb74d533 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -392,6 +392,7 @@ public: static status_t getStreamVolumeIndex(stream_type stream, int *index); static uint32_t getStrategyForStream(stream_type stream); + static uint32_t getDevicesForStream(stream_type stream); static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc); static status_t registerEffect(effect_descriptor_t *desc, diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index 5afceaa4bc4ff..720a562265cee 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -74,6 +74,7 @@ public: virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0; virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0; virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0; + virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream) = 0; virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0; virtual status_t registerEffect(effect_descriptor_t *desc, audio_io_handle_t output, diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 5a59ef6ac809f..cc2ffa074ba39 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -979,7 +979,7 @@ public class AudioManager { * false if otherwise */ public boolean isBluetoothA2dpOn() { - if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,"") + if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_BLUETOOTH_A2DP,"") == AudioSystem.DEVICE_STATE_UNAVAILABLE) { return false; } else { @@ -1004,9 +1004,9 @@ public class AudioManager { * false if otherwise */ public boolean isWiredHeadsetOn() { - if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,"") + if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"") == AudioSystem.DEVICE_STATE_UNAVAILABLE && - AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,"") + AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"") == AudioSystem.DEVICE_STATE_UNAVAILABLE) { return false; } else { @@ -1679,4 +1679,105 @@ public class AudioManager { return silentMode; } + // This section re-defines new output device constants from AudioSystem, because the AudioSystem + // class is not used by other parts of the framework, which instead use definitions and methods + // from AudioManager. AudioSystem is an internal class used by AudioManager and AudioService. + + /** {@hide} The audio output device code for the small speaker at the front of the device used + * when placing calls. Does not refer to an in-ear headphone without attached microphone, + * such as earbuds, earphones, or in-ear monitors (IEM). Those would be handled as a + * {@link #DEVICE_OUT_WIRED_HEADPHONE}. + */ + public static final int DEVICE_OUT_EARPIECE = AudioSystem.DEVICE_OUT_EARPIECE; + /** {@hide} The audio output device code for the built-in speaker */ + public static final int DEVICE_OUT_SPEAKER = AudioSystem.DEVICE_OUT_SPEAKER; + /** {@hide} The audio output device code for a wired headset with attached microphone */ + public static final int DEVICE_OUT_WIRED_HEADSET = AudioSystem.DEVICE_OUT_WIRED_HEADSET; + /** {@hide} The audio output device code for a wired headphone without attached microphone */ + public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; + /** {@hide} The audio output device code for generic Bluetooth SCO, for voice */ + public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; + /** {@hide} The audio output device code for Bluetooth SCO Headset Profile (HSP) and + * Hands-Free Profile (HFP), for voice + */ + public static final int DEVICE_OUT_BLUETOOTH_SCO_HEADSET = + AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; + /** {@hide} The audio output device code for Bluetooth SCO car audio, for voice */ + public static final int DEVICE_OUT_BLUETOOTH_SCO_CARKIT = + AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; + /** {@hide} The audio output device code for generic Bluetooth A2DP, for music */ + public static final int DEVICE_OUT_BLUETOOTH_A2DP = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP; + /** {@hide} The audio output device code for Bluetooth A2DP headphones, for music */ + public static final int DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; + /** {@hide} The audio output device code for Bluetooth A2DP external speaker, for music */ + public static final int DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = + AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; + /** {@hide} The audio output device code for S/PDIF or HDMI */ + public static final int DEVICE_OUT_AUX_DIGITAL = AudioSystem.DEVICE_OUT_AUX_DIGITAL; + /** {@hide} The audio output device code for an analog wired headset attached via a + * docking station + */ + public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; + /** {@hide} The audio output device code for a digital wired headset attached via a + * docking station + */ + public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET; + /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be + * used in the future in a set method to select whatever default device is chosen by the + * platform-specific implementation. + */ + public static final int DEVICE_OUT_DEFAULT = AudioSystem.DEVICE_OUT_DEFAULT; + + /** + * Return the enabled devices for the specified output stream type. + * + * @param streamType The stream type to query. One of + * {@link #STREAM_VOICE_CALL}, + * {@link #STREAM_SYSTEM}, + * {@link #STREAM_RING}, + * {@link #STREAM_MUSIC}, + * {@link #STREAM_ALARM}, + * {@link #STREAM_NOTIFICATION}, + * {@link #STREAM_DTMF}. + * + * @return The bit-mask "or" of audio output device codes for all enabled devices on this + * stream. Zero or more of + * {@link #DEVICE_OUT_EARPIECE}, + * {@link #DEVICE_OUT_SPEAKER}, + * {@link #DEVICE_OUT_WIRED_HEADSET}, + * {@link #DEVICE_OUT_WIRED_HEADPHONE}, + * {@link #DEVICE_OUT_BLUETOOTH_SCO}, + * {@link #DEVICE_OUT_BLUETOOTH_SCO_HEADSET}, + * {@link #DEVICE_OUT_BLUETOOTH_SCO_CARKIT}, + * {@link #DEVICE_OUT_BLUETOOTH_A2DP}, + * {@link #DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES}, + * {@link #DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER}, + * {@link #DEVICE_OUT_AUX_DIGITAL}, + * {@link #DEVICE_OUT_ANLG_DOCK_HEADSET}, + * {@link #DEVICE_OUT_DGTL_DOCK_HEADSET}. + * {@link #DEVICE_OUT_DEFAULT} is not used here. + * + * The implementation may support additional device codes beyond those listed, so + * the application should ignore any bits which it does not recognize. + * Note that the information may be imprecise when the implementation + * cannot distinguish whether a particular device is enabled. + * + * {@hide} + */ + public int getDevicesForStream(int streamType) { + switch (streamType) { + case STREAM_VOICE_CALL: + case STREAM_SYSTEM: + case STREAM_RING: + case STREAM_MUSIC: + case STREAM_ALARM: + case STREAM_NOTIFICATION: + case STREAM_DTMF: + return AudioSystem.getDevicesForStream(streamType); + default: + return 0; + } + } + } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index e20bb2510d9f1..92cc96059c8d8 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -18,7 +18,8 @@ package android.media; /* IF YOU CHANGE ANY OF THE CONSTANTS IN THIS FILE, DO NOT FORGET - * TO UPDATE THE CORRESPONDING NATIVE GLUE. THANK YOU FOR YOUR COOPERATION + * TO UPDATE THE CORRESPONDING NATIVE GLUE AND AudioManager.java. + * THANK YOU FOR YOUR COOPERATION. */ /** @@ -29,7 +30,7 @@ public class AudioSystem /* FIXME: Need to finalize this and correlate with native layer */ /* * If these are modified, please also update Settings.System.VOLUME_SETTINGS - * and attrs.xml + * and attrs.xml and AudioManager.java. */ /* The audio stream for phone calls */ public static final int STREAM_VOICE_CALL = 0; @@ -232,7 +233,7 @@ public class AudioSystem * AudioPolicyService methods */ - // output devices + // output devices, be sure to update AudioManager.java also public static final int DEVICE_OUT_EARPIECE = 0x1; public static final int DEVICE_OUT_SPEAKER = 0x2; public static final int DEVICE_OUT_WIRED_HEADSET = 0x4; @@ -295,4 +296,5 @@ public class AudioSystem public static native int initStreamVolume(int stream, int indexMin, int indexMax); public static native int setStreamVolumeIndex(int stream, int index); public static native int getStreamVolumeIndex(int stream); + public static native int getDevicesForStream(int stream); } diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 9d9b3c08ac9d0..2f694ba59cba9 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -668,6 +668,13 @@ uint32_t AudioSystem::getStrategyForStream(AudioSystem::stream_type stream) return aps->getStrategyForStream(stream); } +uint32_t AudioSystem::getDevicesForStream(AudioSystem::stream_type stream) +{ + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return 0; + return aps->getDevicesForStream(stream); +} + audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc) { const sp& aps = AudioSystem::get_audio_policy_service(); diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 457f7ed7af5ae..b89a27891fcaa 100644 --- a/media/libmedia/IAudioPolicyService.cpp +++ b/media/libmedia/IAudioPolicyService.cpp @@ -49,7 +49,8 @@ enum { GET_OUTPUT_FOR_EFFECT, REGISTER_EFFECT, UNREGISTER_EFFECT, - IS_STREAM_ACTIVE + IS_STREAM_ACTIVE, + GET_DEVICES_FOR_STREAM, }; class BpAudioPolicyService : public BpInterface @@ -263,6 +264,15 @@ public: return reply.readInt32(); } + virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream) + { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.writeInt32(static_cast (stream)); + remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply); + return (uint32_t) reply.readInt32(); + } + virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) { Parcel data, reply; @@ -495,6 +505,14 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case GET_DEVICES_FOR_STREAM: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + AudioSystem::stream_type stream = + static_cast (data.readInt32()); + reply->writeInt32(static_cast (getDevicesForStream(stream))); + return NO_ERROR; + } break; + case GET_OUTPUT_FOR_EFFECT: { CHECK_INTERFACE(IAudioPolicyService, data, reply); effect_descriptor_t desc; diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp index 04d63e6e9aaae..58e9b081d4a8e 100644 --- a/services/audioflinger/AudioPolicyManagerBase.cpp +++ b/services/audioflinger/AudioPolicyManagerBase.cpp @@ -1543,6 +1543,20 @@ uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type s return (uint32_t)getStrategy(stream); } +uint32_t AudioPolicyManagerBase::getDevicesForStream(AudioSystem::stream_type stream) { + uint32_t devices; + // By checking the range of stream before calling getStrategy, we avoid + // getStrategy's behavior for invalid streams. getStrategy would do a LOGE + // and then return STRATEGY_MEDIA, but we want to return the empty set. + if (stream < (AudioSystem::stream_type) 0 || stream >= AudioSystem::NUM_STREAM_TYPES) { + devices = 0; + } else { + AudioPolicyManagerBase::routing_strategy strategy = getStrategy(stream); + devices = getDeviceForStrategy(strategy, true); + } + return devices; +} + AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy( AudioSystem::stream_type stream) { // stream to strategy mapping diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp index 953ddacd7c5a3..b614c483632f9 100644 --- a/services/audioflinger/AudioPolicyService.cpp +++ b/services/audioflinger/AudioPolicyService.cpp @@ -365,6 +365,14 @@ uint32_t AudioPolicyService::getStrategyForStream(AudioSystem::stream_type strea return mpPolicyManager->getStrategyForStream(stream); } +uint32_t AudioPolicyService::getDevicesForStream(AudioSystem::stream_type stream) +{ + if (mpPolicyManager == NULL) { + return 0; + } + return mpPolicyManager->getDevicesForStream(stream); +} + audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc) { if (mpPolicyManager == NULL) { diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h index 4749b8b4f6108..faad893ea9689 100644 --- a/services/audioflinger/AudioPolicyService.h +++ b/services/audioflinger/AudioPolicyService.h @@ -86,6 +86,7 @@ public: virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index); virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream); + virtual uint32_t getDevicesForStream(AudioSystem::stream_type stream); virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc); virtual status_t registerEffect(effect_descriptor_t *desc,