summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2009-10-08 10:58:19 -0700
committer Eric Laurent <elaurent@google.com> 2009-10-08 12:03:51 -0700
commit80a6a229b33b0868944fe011af2d778e23c83322 (patch)
treeb14ae7e641c595cd2e34e5e4daa63ed6d324f300
parentbd324c9bd32a3c86634c1cc1ab8525f46a56b694 (diff)
Fix issue 2174002: After rejecting Call when device ringtone is mute and playing music, audio is not transfered to BT device.
Added a workarouond to request the A2DP output standby directly to audio hardware when the sink is suspended as it seems that the suspend request often fails. Also take into account resume requests received while a suspend request is pending.
-rw-r--r--core/java/android/server/BluetoothA2dpService.java56
-rw-r--r--libs/audioflinger/A2dpAudioInterface.cpp35
-rw-r--r--libs/audioflinger/A2dpAudioInterface.h3
3 files changed, 85 insertions, 9 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index b73e53ffca83..9a2d6d94a934 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -72,6 +72,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
private final AudioManager mAudioManager;
private final BluetoothService mBluetoothService;
private final BluetoothAdapter mAdapter;
+ private boolean mSuspending;
+ private boolean mResuming;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -149,6 +151,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
if (mBluetoothService.isEnabled())
onBluetoothEnable();
+ mSuspending = false;
+ mResuming = false;
}
@Override
@@ -241,6 +245,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
}
mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
+ mAudioManager.setParameters("A2dpSuspended=false");
}
private synchronized void onBluetoothDisable() {
@@ -336,7 +341,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
public synchronized boolean suspendSink(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- if (DBG) log("suspendSink(" + device + ")");
+ if (DBG) log("suspendSink(" + device + "), mSuspending: "+mSuspending+", mResuming: "+mResuming);
+ if (mSuspending) {
+ return true;
+ }
if (device == null || mAudioDevices == null) {
return false;
}
@@ -347,9 +355,14 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
switch (state.intValue()) {
case BluetoothA2dp.STATE_CONNECTED:
+ if (mResuming) {
+ mSuspending = true;
+ }
return true;
case BluetoothA2dp.STATE_PLAYING:
- return suspendSinkNative(path);
+ mAudioManager.setParameters("A2dpSuspended=true");
+ mSuspending = suspendSinkNative(path);
+ return mSuspending;
default:
return false;
}
@@ -358,7 +371,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
public synchronized boolean resumeSink(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- if (DBG) log("resumeSink(" + device + ")");
+ if (DBG) log("resumeSink(" + device + "), mResuming: "+mResuming+", mSuspending: "+mSuspending);
+ if (mResuming) {
+ return true;
+ }
if (device == null || mAudioDevices == null) {
return false;
}
@@ -369,9 +385,14 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
switch (state.intValue()) {
case BluetoothA2dp.STATE_PLAYING:
+ if (mSuspending) {
+ mResuming = true;
+ }
return true;
case BluetoothA2dp.STATE_CONNECTED:
- return resumeSinkNative(path);
+ mResuming = resumeSinkNative(path);
+ mAudioManager.setParameters("A2dpSuspended=false");
+ return mResuming;
default:
return false;
}
@@ -437,6 +458,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
+ if (state == BluetoothA2dp.STATE_DISCONNECTED) {
+ mSuspending = false;
+ mResuming = false;
+ }
if (state != prevState) {
if (state == BluetoothA2dp.STATE_DISCONNECTED ||
state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -452,6 +477,29 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
mAudioDevices.put(device, state);
+ if (state == BluetoothA2dp.STATE_CONNECTED && prevState == BluetoothA2dp.STATE_PLAYING) {
+ if (DBG) log("handleSinkStateChange() STATE_PLAYING -> STATE_CONNECTED: mSuspending: "
+ +mSuspending+", mResuming: "+mResuming);
+ if (mSuspending) {
+ mSuspending = false;
+ if (mResuming) {
+ mResuming = false;
+ resumeSink(device);
+ }
+ }
+ }
+ if (state == BluetoothA2dp.STATE_PLAYING && prevState == BluetoothA2dp.STATE_CONNECTED) {
+ if (DBG) log("handleSinkStateChange() STATE_CONNECTED -> STATE_PLAYING: mSuspending: "
+ +mSuspending+", mResuming: "+mResuming);
+
+ if (mResuming) {
+ mResuming = false;
+ if (mSuspending) {
+ mSuspending = false;
+ suspendSink(device);
+ }
+ }
+ }
Intent intent = new Intent(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, prevState);
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index 57a29f2dc001..351815bdb440 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -16,7 +16,7 @@
#include <math.h>
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "A2dpAudioInterface"
#include <utils/Log.h>
#include <utils/String8.h>
@@ -40,7 +40,7 @@ namespace android {
//}
A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
- mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true)
+ mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
{
}
@@ -78,6 +78,7 @@ AudioStreamOut* A2dpAudioInterface::openOutputStream(
if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
mOutput = out;
mOutput->setBluetoothEnabled(mBluetoothEnabled);
+ mOutput->setSuspended(mSuspended);
} else {
delete out;
}
@@ -142,6 +143,14 @@ status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
}
param.remove(key);
}
+ key = String8("A2dpSuspended");
+ if (param.get(key, value) == NO_ERROR) {
+ mSuspended = (value == "true");
+ if (mOutput) {
+ mOutput->setSuspended(mSuspended);
+ }
+ param.remove(key);
+ }
if (param.size()) {
status_t hwStatus = mHardwareInterface->setParameters(param.toString());
@@ -166,6 +175,12 @@ String8 A2dpAudioInterface::getParameters(const String8& keys)
a2dpParam.add(key, value);
param.remove(key);
}
+ key = "A2dpSuspended";
+ if (param.get(key, value) == NO_ERROR) {
+ value = mSuspended ? "true" : "false";
+ a2dpParam.add(key, value);
+ param.remove(key);
+ }
String8 keyValuePairs = a2dpParam.toString();
@@ -204,7 +219,7 @@ A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
// assume BT enabled to start, this is safe because its only the
// enabled->disabled transition we are worried about
- mBluetoothEnabled(true), mDevice(0), mClosing(false)
+ mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
{
// use any address by default
strcpy(mA2dpAddress, "00:00:00:00:00:00");
@@ -258,8 +273,10 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t
size_t remaining = bytes;
status_t status = -1;
- if (!mBluetoothEnabled || mClosing) {
- LOGW("A2dpAudioStreamOut::write(), but bluetooth disabled");
+ if (!mBluetoothEnabled || mClosing || mSuspended) {
+ LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+ mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+ mBluetoothEnabled, mClosing, mSuspended);
goto Error;
}
@@ -408,6 +425,14 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enable
return NO_ERROR;
}
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
+{
+ LOGV("setSuspended %d", onOff);
+ mSuspended = onOff;
+ standby();
+ return NO_ERROR;
+}
+
status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
{
Mutex::Autolock lock(mLock);
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index 35a6e1188b7d..530e432c6a4a 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -101,6 +101,7 @@ private:
status_t close_l();
status_t setAddress(const char* address);
status_t setBluetoothEnabled(bool enabled);
+ status_t setSuspended(bool onOff);
private:
int mFd;
@@ -113,6 +114,7 @@ private:
bool mBluetoothEnabled;
uint32_t mDevice;
bool mClosing;
+ bool mSuspended;
};
friend class A2dpAudioStreamOut;
@@ -121,6 +123,7 @@ private:
AudioHardwareInterface *mHardwareInterface;
char mA2dpAddress[20];
bool mBluetoothEnabled;
+ bool mSuspended;
};