diff options
-rw-r--r-- | core/java/android/server/BluetoothA2dpService.java | 56 | ||||
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.cpp | 35 | ||||
-rw-r--r-- | libs/audioflinger/A2dpAudioInterface.h | 3 |
3 files changed, 85 insertions, 9 deletions
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index b73e53f..9a2d6d9 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 57a29f2..351815b 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 35a6e11..530e432 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; }; |