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

Commit d094bc7c authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "AudioService: handle SCO audio activaton for regular VoIP apps" into main

parents 0088e07b 429defcc
Loading
Loading
Loading
Loading
+91 −19
Original line number Original line Diff line number Diff line
@@ -51,6 +51,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
@@ -374,6 +375,16 @@ public class AudioDeviceBroker {
                deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource);
                deviceInfo.mScoAudioMode, deviceInfo.mIsPrivileged, deviceInfo.mEventSource);
    }
    }


    /**
     * Indicates if a Bluetooth SCO activation request owner is controlling
     * the SCO audio state itself or not.
     * @param uid the UI of the SOC request owner app
     * @return true if we should control SCO audio state, false otherwise
     */
    private boolean shouldStartScoForUid(int uid) {
        return !(uid == Process.BLUETOOTH_UID || uid == Process.PHONE_UID);
    }

    @GuardedBy("mDeviceStateLock")
    @GuardedBy("mDeviceStateLock")
    /*package*/ void setCommunicationRouteForClient(
    /*package*/ void setCommunicationRouteForClient(
                            IBinder cb, int uid, AudioDeviceAttributes device,
                            IBinder cb, int uid, AudioDeviceAttributes device,
@@ -388,7 +399,7 @@ public class AudioDeviceBroker {
                                        + " device: " + device + " isPrivileged: " + isPrivileged
                                        + " device: " + device + " isPrivileged: " + isPrivileged
                                        + " from API: " + eventSource)).printLog(TAG));
                                        + " from API: " + eventSource)).printLog(TAG));


        final boolean wasBtScoRequested = isBluetoothScoRequested();
        final int previousBtScoRequesterUid = bluetoothScoRequestOwnerUid();
        CommunicationRouteClient client;
        CommunicationRouteClient client;


        // Save previous client route in case of failure to start BT SCO audio
        // Save previous client route in case of failure to start BT SCO audio
@@ -412,8 +423,40 @@ public class AudioDeviceBroker {
        if (client == null) {
        if (client == null) {
            return;
            return;
        }
        }
        if (!mScoManagedByAudio) {
        final int btScoRequesterUid = bluetoothScoRequestOwnerUid();
            boolean isBtScoRequested = isBluetoothScoRequested();
        final boolean isBtScoRequested = btScoRequesterUid != -1;
        final boolean wasBtScoRequested = previousBtScoRequesterUid != -1;

        if (mScoManagedByAudio) {
            if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive()
                    || !mBtHelper.isBluetoothScoRequestedInternally())) {
                boolean scoStarted = false;
                if (shouldStartScoForUid(btScoRequesterUid)) {
                    scoStarted = mBtHelper.startBluetoothSco(scoAudioMode, eventSource);
                    if (!scoStarted) {
                        Log.w(TAG, "setCommunicationRouteForClient: "
                                + "failure to start BT SCO for uid: " + uid);
                        // clean up or restore previous client selection
                        if (prevClientDevice != null) {
                            addCommunicationRouteClient(cb, uid, prevClientDevice, prevPrivileged);
                        } else {
                            removeCommunicationRouteClient(cb, true);
                        }
                        postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
                    }
                } else {
                    scoStarted = true;
                }
                if (scoStarted) {
                    setBluetoothScoOn(true, "setCommunicationRouteForClient");
                }
            } else if (!isBtScoRequested && wasBtScoRequested) {
                if (shouldStartScoForUid(previousBtScoRequesterUid)) {
                    mBtHelper.stopBluetoothSco(eventSource);
                }
                setBluetoothScoOn(false, "setCommunicationRouteForClient");
            }
        } else {
            if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive()
            if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive()
                    || !mBtHelper.isBluetoothScoRequestedInternally())) {
                    || !mBtHelper.isBluetoothScoRequestedInternally())) {
                if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
                if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
@@ -575,12 +618,12 @@ public class AudioDeviceBroker {
    @GuardedBy("mDeviceStateLock")
    @GuardedBy("mDeviceStateLock")
    /*package*/ void updateCommunicationRouteClientState(
    /*package*/ void updateCommunicationRouteClientState(
                            CommunicationRouteClient client, boolean wasActive) {
                            CommunicationRouteClient client, boolean wasActive) {
        boolean wasBtScoRequested = isBluetoothScoRequested();
        int btScoRequesterUid = bluetoothScoRequestOwnerUid();
        client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid()));
        client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid()));
        client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid()));
        client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid()));
        if (wasActive != client.isActive()) {
        if (wasActive != client.isActive()) {
            postUpdateCommunicationRouteClient(
            postUpdateCommunicationRouteClient(
                    wasBtScoRequested, "updateCommunicationRouteClientState");
                    btScoRequesterUid, "updateCommunicationRouteClientState");
        }
        }
    }
    }


@@ -762,6 +805,22 @@ public class AudioDeviceBroker {
        return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
        return isDeviceRequestedForCommunication(AudioDeviceInfo.TYPE_BLUETOOTH_SCO);
    }
    }


    /**
     * Helper method on top of isBluetoothScoRequested() returning the UID of the
     * BT SCO route request owner of -1 if SCO is not requested.
     * @return the UID of the BT SCO route request owner of -1 if SCO is not requested.
     */
    @GuardedBy("mDeviceStateLock")
    /*package*/ int bluetoothScoRequestOwnerUid() {
        if (!isBluetoothScoRequested()) {
            return -1;
        }
        CommunicationRouteClient crc = topCommunicationRouteClient();
        if (crc == null) {
            return -1;
        }
        return crc.getUid();
    }
    /**
    /**
     * Helper method on top of isDeviceRequestedForCommunication() indicating if
     * Helper method on top of isDeviceRequestedForCommunication() indicating if
     * Bluetooth LE Audio communication device is currently requested or not.
     * Bluetooth LE Audio communication device is currently requested or not.
@@ -1148,15 +1207,18 @@ public class AudioDeviceBroker {
        }
        }
    }
    }


    @GuardedBy("mDeviceStateLock")
    /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
    /*package*/ void setBluetoothScoOn(boolean on, String eventSource) {
        synchronized (mBluetoothAudioStateLock) {
        synchronized (mBluetoothAudioStateLock) {
            boolean isBtScoRequested = isBluetoothScoRequested();
            int btScoRequesterUId = bluetoothScoRequestOwnerUid();
            Log.i(TAG, "setBluetoothScoOn: " + on + ", mBluetoothScoOn: "
            Log.i(TAG, "setBluetoothScoOn: " + on + ", mBluetoothScoOn: "
                    + mBluetoothScoOn + ", isBtScoRequested: " + isBtScoRequested
                    + mBluetoothScoOn + ", btScoRequesterUId: " + btScoRequesterUId
                    + ", from: " + eventSource);
                    + ", from: " + eventSource);
            mBluetoothScoOn = on;
            mBluetoothScoOn = on;
            updateAudioHalBluetoothState();
            updateAudioHalBluetoothState();
            postUpdateCommunicationRouteClient(isBtScoRequested, eventSource);
            if (!mScoManagedByAudio) {
                postUpdateCommunicationRouteClient(btScoRequesterUId, eventSource);
            }
        }
        }
    }
    }


@@ -1510,9 +1572,9 @@ public class AudioDeviceBroker {
    }
    }


    /*package*/ void postUpdateCommunicationRouteClient(
    /*package*/ void postUpdateCommunicationRouteClient(
            boolean wasBtScoRequested, String eventSource) {
            int btScoRequesterUid, String eventSource) {
        sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE,
        sendILMsgNoDelay(MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE,
                wasBtScoRequested ? 1 : 0, eventSource);
                btScoRequesterUid, eventSource);
    }
    }


    /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) {
    /*package*/ void postSetCommunicationDeviceForClient(CommunicationDeviceInfo info) {
@@ -1865,7 +1927,7 @@ public class AudioDeviceBroker {
                                        || btInfo.mProfile == BluetoothProfile.HEARING_AID
                                        || btInfo.mProfile == BluetoothProfile.HEARING_AID
                                        || (mScoManagedByAudio
                                        || (mScoManagedByAudio
                                            && btInfo.mProfile == BluetoothProfile.HEADSET)) {
                                            && btInfo.mProfile == BluetoothProfile.HEADSET)) {
                                    onUpdateCommunicationRouteClient(isBluetoothScoRequested(),
                                    onUpdateCommunicationRouteClient(bluetoothScoRequestOwnerUid(),
                                            "setBluetoothActiveDevice");
                                            "setBluetoothActiveDevice");
                                }
                                }
                            }
                            }
@@ -1927,11 +1989,11 @@ public class AudioDeviceBroker {
                case MSG_I_SET_MODE_OWNER:
                case MSG_I_SET_MODE_OWNER:
                    synchronized (mSetModeLock) {
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                        synchronized (mDeviceStateLock) {
                            boolean wasBtScoRequested = isBluetoothScoRequested();
                            int btScoRequesterUid = bluetoothScoRequestOwnerUid();
                            mAudioModeOwner = (AudioModeInfo) msg.obj;
                            mAudioModeOwner = (AudioModeInfo) msg.obj;
                            if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
                            if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
                                onUpdateCommunicationRouteClient(
                                onUpdateCommunicationRouteClient(
                                        wasBtScoRequested, "setNewModeOwner");
                                        btScoRequesterUid, "setNewModeOwner");
                            }
                            }
                        }
                        }
                    }
                    }
@@ -1958,7 +2020,7 @@ public class AudioDeviceBroker {
                case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT:
                case MSG_IL_UPDATE_COMMUNICATION_ROUTE_CLIENT:
                    synchronized (mSetModeLock) {
                    synchronized (mSetModeLock) {
                        synchronized (mDeviceStateLock) {
                        synchronized (mDeviceStateLock) {
                            onUpdateCommunicationRouteClient(msg.arg1 == 1, (String) msg.obj);
                            onUpdateCommunicationRouteClient(msg.arg1, (String) msg.obj);
                        }
                        }
                    }
                    }
                    break;
                    break;
@@ -2457,7 +2519,7 @@ public class AudioDeviceBroker {
    @Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
    @Nullable private AudioDeviceAttributes preferredCommunicationDevice() {
        boolean btSCoOn = mBtHelper.isBluetoothScoOn();
        boolean btSCoOn = mBtHelper.isBluetoothScoOn();
        synchronized (mBluetoothAudioStateLock) {
        synchronized (mBluetoothAudioStateLock) {
            btSCoOn = btSCoOn && mBluetoothScoOn;
            btSCoOn = (btSCoOn || mScoManagedByAudio) && mBluetoothScoOn;
        }
        }


        if (btSCoOn) {
        if (btSCoOn) {
@@ -2522,19 +2584,29 @@ public class AudioDeviceBroker {
     */
     */
    // @GuardedBy("mSetModeLock")
    // @GuardedBy("mSetModeLock")
    @GuardedBy("mDeviceStateLock")
    @GuardedBy("mDeviceStateLock")
    private void onUpdateCommunicationRouteClient(boolean wasBtScoRequested, String eventSource) {
    private void onUpdateCommunicationRouteClient(
            int previousBtScoRequesterUid, String eventSource) {
        CommunicationRouteClient crc = topCommunicationRouteClient();
        CommunicationRouteClient crc = topCommunicationRouteClient();
        if (AudioService.DEBUG_COMM_RTE) {
        if (AudioService.DEBUG_COMM_RTE) {
            Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc
            Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + crc
                    + " wasBtScoRequested: " + wasBtScoRequested + " eventSource: " + eventSource);
                    + " previousBtScoRequesterUid: " + previousBtScoRequesterUid
                    + " eventSource: " + eventSource);
        }
        }
        if (crc != null) {
        if (crc != null) {
            setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
            setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
                    BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
                    BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
        } else {
        } else {
            if (!mScoManagedByAudio && !isBluetoothScoRequested() && wasBtScoRequested) {
            boolean wasScoRequested = previousBtScoRequesterUid != -1;
            if (!isBluetoothScoRequested() && wasScoRequested) {
                if (mScoManagedByAudio) {
                    if (shouldStartScoForUid(previousBtScoRequesterUid)) {
                        mBtHelper.stopBluetoothSco(eventSource);
                        mBtHelper.stopBluetoothSco(eventSource);
                    }
                    }
                    setBluetoothScoOn(false, eventSource);
                } else {
                    mBtHelper.stopBluetoothSco(eventSource);
                }
            }
            updateCommunicationRoute(eventSource);
            updateCommunicationRoute(eventSource);
        }
        }
    }
    }
+46 −57
Original line number Original line Diff line number Diff line
@@ -401,23 +401,8 @@ public class BtHelper {
    private void onScoAudioStateChanged(int state) {
    private void onScoAudioStateChanged(int state) {
        boolean broadcast = false;
        boolean broadcast = false;
        int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
        int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
        Log.i(TAG, "onScoAudioStateChanged state: " + state + " mScoAudioState: " + mScoAudioState);
        Log.i(TAG, "onScoAudioStateChanged  state: " + state
        if (mDeviceBroker.isScoManagedByAudio()) {
                + ", mScoAudioState: " + mScoAudioState);
            switch (state) {
                case BluetoothHeadset.STATE_AUDIO_CONNECTED:
                    mDeviceBroker.setBluetoothScoOn(true, "BtHelper.onScoAudioStateChanged");
                    scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
                    broadcast = true;
                    break;
                case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
                    mDeviceBroker.setBluetoothScoOn(false, "BtHelper.onScoAudioStateChanged");
                    scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                    broadcast = true;
                    break;
                default:
                    break;
            }
        } else {
        switch (state) {
        switch (state) {
            case BluetoothHeadset.STATE_AUDIO_CONNECTED:
            case BluetoothHeadset.STATE_AUDIO_CONNECTED:
                scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
                scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
@@ -428,10 +413,14 @@ public class BtHelper {
                    // broadcast intent if the connection was initated by AudioService
                    // broadcast intent if the connection was initated by AudioService
                    broadcast = true;
                    broadcast = true;
                }
                }
                if (!mDeviceBroker.isScoManagedByAudio()) {
                    mDeviceBroker.setBluetoothScoOn(true, "BtHelper.onScoAudioStateChanged");
                    mDeviceBroker.setBluetoothScoOn(true, "BtHelper.onScoAudioStateChanged");
                }
                break;
                break;
            case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
            case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
                if (!mDeviceBroker.isScoManagedByAudio()) {
                    mDeviceBroker.setBluetoothScoOn(false, "BtHelper.onScoAudioStateChanged");
                    mDeviceBroker.setBluetoothScoOn(false, "BtHelper.onScoAudioStateChanged");
                }
                scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                // There are two cases where we want to immediately reconnect audio:
                // There are two cases where we want to immediately reconnect audio:
                // 1) If a new start request was received while disconnecting: this was
                // 1) If a new start request was received while disconnecting: this was
@@ -463,8 +452,8 @@ public class BtHelper {
            default:
            default:
                break;
                break;
        }
        }
        }
        if (broadcast) {
        if (broadcast) {
            Log.i(TAG, "onScoAudioStateChanged  broadcasting state: " + scoAudioState);
            broadcastScoConnectionState(scoAudioState);
            broadcastScoConnectionState(scoAudioState);
            //FIXME: this is to maintain compatibility with deprecated intent
            //FIXME: this is to maintain compatibility with deprecated intent
            // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
            // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.