Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80a6a229 authored by Eric Laurent's avatar Eric Laurent
Browse files

Fix issue 2174002: After rejecting Call when device ringtone is mute and...

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.
parent bd324c9b
Loading
Loading
Loading
Loading
+52 −4
Original line number Original line Diff line number Diff line
@@ -72,6 +72,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
    private final AudioManager mAudioManager;
    private final AudioManager mAudioManager;
    private final BluetoothService mBluetoothService;
    private final BluetoothService mBluetoothService;
    private final BluetoothAdapter mAdapter;
    private final BluetoothAdapter mAdapter;
    private boolean mSuspending;
    private boolean mResuming;


    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        @Override
@@ -149,6 +151,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {


        if (mBluetoothService.isEnabled())
        if (mBluetoothService.isEnabled())
            onBluetoothEnable();
            onBluetoothEnable();
        mSuspending = false;
        mResuming = false;
    }
    }


    @Override
    @Override
@@ -241,6 +245,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
                }
                }
        }
        }
        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
        mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
        mAudioManager.setParameters("A2dpSuspended=false");
    }
    }


    private synchronized void onBluetoothDisable() {
    private synchronized void onBluetoothDisable() {
@@ -336,7 +341,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
    public synchronized boolean suspendSink(BluetoothDevice device) {
    public synchronized boolean suspendSink(BluetoothDevice device) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                            "Need BLUETOOTH_ADMIN permission");
                            "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) {
        if (device == null || mAudioDevices == null) {
            return false;
            return false;
        }
        }
@@ -347,9 +355,14 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
        }
        }
        switch (state.intValue()) {
        switch (state.intValue()) {
        case BluetoothA2dp.STATE_CONNECTED:
        case BluetoothA2dp.STATE_CONNECTED:
            if (mResuming) {
                mSuspending = true;
            }
            return true;
            return true;
        case BluetoothA2dp.STATE_PLAYING:
        case BluetoothA2dp.STATE_PLAYING:
            return suspendSinkNative(path);
            mAudioManager.setParameters("A2dpSuspended=true");
            mSuspending = suspendSinkNative(path);
            return mSuspending;
        default:
        default:
            return false;
            return false;
        }
        }
@@ -358,7 +371,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
    public synchronized boolean resumeSink(BluetoothDevice device) {
    public synchronized boolean resumeSink(BluetoothDevice device) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                            "Need BLUETOOTH_ADMIN permission");
                            "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) {
        if (device == null || mAudioDevices == null) {
            return false;
            return false;
        }
        }
@@ -369,9 +385,14 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
        }
        }
        switch (state.intValue()) {
        switch (state.intValue()) {
        case BluetoothA2dp.STATE_PLAYING:
        case BluetoothA2dp.STATE_PLAYING:
            if (mSuspending) {
                mResuming = true;
            }
            return true;
            return true;
        case BluetoothA2dp.STATE_CONNECTED:
        case BluetoothA2dp.STATE_CONNECTED:
            return resumeSinkNative(path);
            mResuming = resumeSinkNative(path);
            mAudioManager.setParameters("A2dpSuspended=false");
            return mResuming;
        default:
        default:
            return false;
            return false;
        }
        }
@@ -437,6 +458,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
    }
    }


    private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
    private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
        if (state == BluetoothA2dp.STATE_DISCONNECTED) {
            mSuspending = false;
            mResuming = false;
        }
        if (state != prevState) {
        if (state != prevState) {
            if (state == BluetoothA2dp.STATE_DISCONNECTED ||
            if (state == BluetoothA2dp.STATE_DISCONNECTED ||
                    state == BluetoothA2dp.STATE_DISCONNECTING) {
                    state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -452,6 +477,29 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
            }
            }
            mAudioDevices.put(device, state);
            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 intent = new Intent(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            intent.putExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, prevState);
            intent.putExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, prevState);
+30 −5
Original line number Original line Diff line number Diff line
@@ -16,7 +16,7 @@


#include <math.h>
#include <math.h>


#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#define LOG_TAG "A2dpAudioInterface"
#define LOG_TAG "A2dpAudioInterface"
#include <utils/Log.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/String8.h>
@@ -40,7 +40,7 @@ namespace android {
//}
//}


A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
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) {
    if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
        mOutput = out;
        mOutput = out;
        mOutput->setBluetoothEnabled(mBluetoothEnabled);
        mOutput->setBluetoothEnabled(mBluetoothEnabled);
        mOutput->setSuspended(mSuspended);
    } else {
    } else {
        delete out;
        delete out;
    }
    }
@@ -142,6 +143,14 @@ status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
        }
        }
        param.remove(key);
        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()) {
    if (param.size()) {
        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
@@ -166,6 +175,12 @@ String8 A2dpAudioInterface::getParameters(const String8& keys)
        a2dpParam.add(key, value);
        a2dpParam.add(key, value);
        param.remove(key);
        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();
    String8 keyValuePairs  = a2dpParam.toString();


@@ -204,7 +219,7 @@ A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
    // assume BT enabled to start, this is safe because its only the
    // assume BT enabled to start, this is safe because its only the
    // enabled->disabled transition we are worried about
    // 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
    // use any address by default
    strcpy(mA2dpAddress, "00:00:00:00:00:00");
    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;
    size_t remaining = bytes;
    status_t status = -1;
    status_t status = -1;


    if (!mBluetoothEnabled || mClosing) {
    if (!mBluetoothEnabled || mClosing || mSuspended) {
        LOGW("A2dpAudioStreamOut::write(), but bluetooth disabled");
        LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
               mBluetoothEnabled %d, mClosing %d, mSuspended %d",
                mBluetoothEnabled, mClosing, mSuspended);
        goto Error;
        goto Error;
    }
    }


@@ -408,6 +425,14 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enable
    return NO_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()
status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
{
{
    Mutex::Autolock lock(mLock);
    Mutex::Autolock lock(mLock);
+3 −0
Original line number Original line Diff line number Diff line
@@ -101,6 +101,7 @@ private:
                status_t    close_l();
                status_t    close_l();
                status_t    setAddress(const char* address);
                status_t    setAddress(const char* address);
                status_t    setBluetoothEnabled(bool enabled);
                status_t    setBluetoothEnabled(bool enabled);
                status_t    setSuspended(bool onOff);


    private:
    private:
                int         mFd;
                int         mFd;
@@ -113,6 +114,7 @@ private:
                bool        mBluetoothEnabled;
                bool        mBluetoothEnabled;
                uint32_t    mDevice;
                uint32_t    mDevice;
                bool        mClosing;
                bool        mClosing;
                bool        mSuspended;
    };
    };


    friend class A2dpAudioStreamOut;
    friend class A2dpAudioStreamOut;
@@ -121,6 +123,7 @@ private:
    AudioHardwareInterface  *mHardwareInterface;
    AudioHardwareInterface  *mHardwareInterface;
    char        mA2dpAddress[20];
    char        mA2dpAddress[20];
    bool        mBluetoothEnabled;
    bool        mBluetoothEnabled;
    bool        mSuspended;
};
};