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
if (mBluetoothService.isEnabled())
onBluetoothEnable();
+ mSuspending = false;
+ mResuming = false;
}
@Override
}
}
mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
+ mAudioManager.setParameters("A2dpSuspended=false");
}
private synchronized void onBluetoothDisable() {
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;
}
}
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;
}
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;
}
}
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;
}
}
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) {
}
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);
#include <math.h>
-#define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define LOG_TAG "A2dpAudioInterface"
#include <utils/Log.h>
#include <utils/String8.h>
//}
A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
- mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true)
+ mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
{
}
if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
mOutput = out;
mOutput->setBluetoothEnabled(mBluetoothEnabled);
+ mOutput->setSuspended(mSuspended);
} else {
delete out;
}
}
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());
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();
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");
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;
}
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);