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

Commit ebd52853 authored by Jack He's avatar Jack He Committed by Android (Google) Code Review
Browse files

Merge changes I553daab5,I4f467864,I6f9deb17,Ic23977b5,I32dca835, ... into tm-qpr-dev

* changes:
  Revert "Lazy activation of A2DP or HFP"
  Revert "Remove OnModeChangedListener when cleanup"
  Revert "Suppress noisy intent when there is a fallback BT device"
  Revert "Refactor ActiveDeviceManager with isMediaMode"
  Revert "Make BT audio routing more resemble the Android S behavior"
  Revert "Call setActiveDevice(null) when disconnected"
parents 96277694 5e7667e8
Loading
Loading
Loading
Loading
+26 −18
Original line number Diff line number Diff line
@@ -494,13 +494,32 @@ public class A2dpService extends ProfileService {
                previousActiveDevice = mActiveDevice;
            }

            int prevActiveConnectionState = getConnectionState(previousActiveDevice);

            // As per b/202602952, if we remove the active device due to a disconnection,
            // we need to check if another device is connected and set it active instead.
            // Calling this before any other active related calls has the same effect as
            // a classic active device switch.
            BluetoothDevice fallbackdevice = getFallbackDevice();
            if (fallbackdevice != null && prevActiveConnectionState
                    != BluetoothProfile.STATE_CONNECTED) {
                setActiveDevice(fallbackdevice);
                return;
            }

            // This needs to happen before we inform the audio manager that the device
            // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
            updateAndBroadcastActiveDevice(null);

            // Make sure the Audio Manager knows the previous Active device is removed.
            // Make sure the Audio Manager knows the previous Active device is disconnected.
            // However, if A2DP is still connected and not forcing stop audio for that remote
            // device, the user has explicitly switched the output to the local device and music
            // should continue playing. Otherwise, the remote device has been indeed disconnected
            // and audio should be suspended before switching the output to the local device.
            boolean stopAudio = forceStopPlayingAudio || (prevActiveConnectionState
                        != BluetoothProfile.STATE_CONNECTED);
            mAudioManager.handleBluetoothActiveDeviceChanged(null, previousActiveDevice,
                    BluetoothProfileConnectionInfo.createA2dpInfo(!forceStopPlayingAudio, -1));
                    BluetoothProfileConnectionInfo.createA2dpInfo(!stopAudio, -1));

            synchronized (mStateMachines) {
                // Make sure the Active device in native layer is set to null and audio is off
@@ -544,22 +563,10 @@ public class A2dpService extends ProfileService {
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device) {
        return setActiveDevice(device, false);
    }

    /**
     * Set the active device.
     *
     * @param device the active device
     * @param hasFallbackDevice whether it has fallback device when the {@code device}
     *                          is {@code null}.
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device, boolean hasFallbackDevice) {
        synchronized (mActiveSwitchingGuard) {
            if (device == null) {
                // Remove active device and continue playing audio only if necessary.
                removeActiveDevice(!hasFallbackDevice);
                removeActiveDevice(false);
                return true;
            }

@@ -1246,9 +1253,10 @@ public class A2dpService extends ProfileService {
        if (toState == BluetoothProfile.STATE_CONNECTED && (mMaxConnectedAudioDevices == 1)) {
            setActiveDevice(device);
        }

        // When disconnected, ActiveDeviceManager will call setActiveDevice(null)

        // Check if the active device is not connected anymore
        if (isActiveDevice(device) && (fromState == BluetoothProfile.STATE_CONNECTED)) {
            setActiveDevice(null);
        }
        // Check if the device is disconnected - if unbond, remove the state machine
        if (toState == BluetoothProfile.STATE_DISCONNECTED) {
            if (mAdapterService.getBondState(device) == BluetoothDevice.BOND_NONE) {
+100 −417

File changed.

Preview size limit exceeded, changes collapsed.

+12 −16
Original line number Diff line number Diff line
@@ -585,24 +585,13 @@ public class HearingAidService extends ProfileService {
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device) {
        return setActiveDevice(device, false);
    }

    /**
     * Set the active device.
     * @param device the new active device
     * @param hasFallbackDevice whether it has fallback device when the {@code device}
     *                          is {@code null}.
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device, boolean hasFallbackDevice) {
        if (DBG) {
            Log.d(TAG, "setActiveDevice:" + device);
        }
        synchronized (mStateMachines) {
            if (device == null) {
                if (mActiveDeviceHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
                    reportActiveDevice(null, hasFallbackDevice);
                    reportActiveDevice(null);
                    mActiveDeviceHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
                }
                return true;
@@ -621,7 +610,7 @@ public class HearingAidService extends ProfileService {
                    BluetoothHearingAid.HI_SYNC_ID_INVALID);
            if (deviceHiSyncId != mActiveDeviceHiSyncId) {
                mActiveDeviceHiSyncId = deviceHiSyncId;
                reportActiveDevice(device, false);
                reportActiveDevice(device);
            }
        }
        return true;
@@ -772,7 +761,7 @@ public class HearingAidService extends ProfileService {
     * Report the active device change to the active device manager and the media framework.
     * @param device the new active device; or null if no active device
     */
    private void reportActiveDevice(BluetoothDevice device, boolean hasFallbackDevice) {
    private void reportActiveDevice(BluetoothDevice device) {
        if (DBG) {
            Log.d(TAG, "reportActiveDevice(" + device + ")");
        }
@@ -783,7 +772,14 @@ public class HearingAidService extends ProfileService {
                BluetoothProfile.HEARING_AID, mAdapterService.obfuscateAddress(device),
                mAdapterService.getMetricId(device));

        boolean stopAudio = device == null && !hasFallbackDevice;
        Intent intent = new Intent(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions());

        boolean stopAudio = device == null
                && (getConnectionState(mPreviousAudioDevice) != BluetoothProfile.STATE_CONNECTED);
        if (DBG) {
            Log.d(TAG, "Hearing Aid audio: " + mPreviousAudioDevice + " -> " + device
                    + ". Stop audio: " + stopAudio);
@@ -899,7 +895,7 @@ public class HearingAidService extends ProfileService {
            }
        }
        if (fromState == BluetoothProfile.STATE_CONNECTED && getConnectedDevices().isEmpty()) {
            // When disconnected, ActiveDeviceManager will call setActiveDevice(null)
            setActiveDevice(null);
            long myHiSyncId = getHiSyncId(device);
            mHiSyncIdConnectedMap.put(myHiSyncId, false);
        }
+113 −108
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ public class LeAudioService extends ProfileService {
    private final Map<BluetoothDevice, Integer> mDeviceAudioLocationMap = new ConcurrentHashMap<>();

    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
    private BroadcastReceiver mMuteStateChangedReceiver;
    private int mStoredRingerMode = -1;
    private Handler mHandler = new Handler(Looper.getMainLooper());
@@ -234,6 +235,10 @@ public class LeAudioService extends ProfileService {
        mBondStateChangedReceiver = new BondStateChangedReceiver();
        registerReceiver(mBondStateChangedReceiver, filter);
        filter = new IntentFilter();
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        mConnectionStateChangedReceiver = new ConnectionStateChangedReceiver();
        registerReceiver(mConnectionStateChangedReceiver, filter);
        filter = new IntentFilter();
        filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
        mMuteStateChangedReceiver = new MuteStateChangedReceiver();
        registerReceiver(mMuteStateChangedReceiver, filter);
@@ -338,6 +343,8 @@ public class LeAudioService extends ProfileService {
        // Unregister broadcast receivers
        unregisterReceiver(mBondStateChangedReceiver);
        mBondStateChangedReceiver = null;
        unregisterReceiver(mConnectionStateChangedReceiver);
        mConnectionStateChangedReceiver = null;
        unregisterReceiver(mMuteStateChangedReceiver);
        mMuteStateChangedReceiver = null;

@@ -818,6 +825,12 @@ public class LeAudioService extends ProfileService {
        if (!Objects.equals(device, previousInDevice)
                || (oldSupportedByDeviceInput != newSupportedByDeviceInput)) {
            mActiveAudioInDevice = newSupportedByDeviceInput ? device : null;
            if (DBG) {
                Log.d(TAG, " handleBluetoothActiveDeviceChanged  previousInDevice: "
                        + previousInDevice + ", mActiveAudioInDevice" + mActiveAudioInDevice
                        + " isLeOutput: false");
            }

            return true;
        }
        Log.d(TAG, "updateActiveInDevice: Nothing to do.");
@@ -870,6 +883,11 @@ public class LeAudioService extends ProfileService {
        if (!Objects.equals(device, previousOutDevice)
                || (oldSupportedByDeviceOutput != newSupportedByDeviceOutput)) {
            mActiveAudioOutDevice = newSupportedByDeviceOutput ? device : null;
            if (DBG) {
                Log.d(TAG, " handleBluetoothActiveDeviceChanged previousOutDevice: "
                        + previousOutDevice + ", mActiveOutDevice: " + mActiveAudioOutDevice
                        + " isLeOutput: true");
            }
            return true;
        }
        Log.d(TAG, "updateActiveOutDevice: Nothing to do.");
@@ -929,12 +947,6 @@ public class LeAudioService extends ProfileService {
     */
    private boolean updateActiveDevices(Integer groupId, Integer oldSupportedAudioDirections,
            Integer newSupportedAudioDirections, boolean isActive) {
        return updateActiveDevices(groupId, oldSupportedAudioDirections,
                newSupportedAudioDirections, isActive, false);
    }

    private boolean updateActiveDevices(Integer groupId, Integer oldSupportedAudioDirections,
            Integer newSupportedAudioDirections, boolean isActive, boolean hasFallbackDevice) {
        BluetoothDevice device = null;
        BluetoothDevice previousActiveOutDevice = mActiveAudioOutDevice;
        BluetoothDevice previousActiveInDevice = mActiveAudioInDevice;
@@ -943,19 +955,19 @@ public class LeAudioService extends ProfileService {
            device = getFirstDeviceFromGroup(groupId);
        }

        boolean isActiveOutDeviceChanged = updateActiveOutDevice(device, groupId,
        boolean isNewActiveOutDevice = updateActiveOutDevice(device, groupId,
                oldSupportedAudioDirections, newSupportedAudioDirections);
        boolean isActiveInDeviceChanged = updateActiveInDevice(device, groupId,
        boolean isNewActiveInDevice = updateActiveInDevice(device, groupId,
                oldSupportedAudioDirections, newSupportedAudioDirections);

        if (DBG) {
            Log.d(TAG, " isActiveOutDeviceUpdated: " + isActiveOutDeviceChanged + ", "
                    + mActiveAudioOutDevice + ", isActiveInDeviceUpdated: "
                    + isActiveInDeviceChanged + ", " + mActiveAudioInDevice);
            Log.d(TAG, " isNewActiveOutDevice: " + isNewActiveOutDevice + ", "
                    + mActiveAudioOutDevice + ", isNewActiveInDevice: " + isNewActiveInDevice
                    + ", " + mActiveAudioInDevice);
        }

        /* Active device changed, there is need to inform about new active LE Audio device */
        if (isActiveOutDeviceChanged || isActiveInDeviceChanged) {
        if (isNewActiveOutDevice || isNewActiveInDevice) {
            /* Register for new device connection/disconnection in Audio Manager */
            if (mActiveAudioOutDevice != null || mActiveAudioInDevice != null) {
                /* Register for any device connection in case if any of devices become connected */
@@ -968,14 +980,14 @@ public class LeAudioService extends ProfileService {
            }
        }

        if (isActiveOutDeviceChanged) {
        if (isNewActiveOutDevice) {
            int volume = IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME;

            if (mActiveAudioOutDevice != null) {
                volume = getAudioDeviceGroupVolume(groupId);
            }

            final boolean suppressNoisyIntent = hasFallbackDevice || (mActiveAudioOutDevice != null)
            final boolean suppressNoisyIntent = (mActiveAudioOutDevice != null)
                    || (getConnectionState(previousActiveOutDevice)
                    == BluetoothProfile.STATE_CONNECTED);

@@ -983,7 +995,7 @@ public class LeAudioService extends ProfileService {
                    previousActiveOutDevice, getLeAudioOutputProfile(suppressNoisyIntent, volume));
        }

        if (isActiveInDeviceChanged) {
        if (isNewActiveInDevice) {
            mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice,
                    previousActiveInDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(false,
                            false));
@@ -996,10 +1008,6 @@ public class LeAudioService extends ProfileService {
     * Set the active device group.
     */
    private void setActiveGroupWithDevice(BluetoothDevice device) {
        setActiveGroupWithDevice(device, false);
    }

    private void setActiveGroupWithDevice(BluetoothDevice device, boolean hasFallbackDevice) {
        int groupId = LE_AUDIO_GROUP_ID_INVALID;

        if (device != null) {
@@ -1030,7 +1038,7 @@ public class LeAudioService extends ProfileService {
             * However we would like to notify audio framework that LeAudio is not
             * active anymore and does not want to get more audio data.
             */
            handleGroupTransitToInactive(currentlyActiveGroupId, hasFallbackDevice);
            handleGroupTransitToInactive(currentlyActiveGroupId);
        }
    }

@@ -1041,21 +1049,9 @@ public class LeAudioService extends ProfileService {
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device) {
        return setActiveDevice(device, false);
    }

    /**
     * Set the active group represented by device.
     *
     * @param device the new active device
     * @param hasFallbackDevice whether it has fallback device when the {@code device}
     *                          is {@code null}.
     * @return true on success, otherwise false
     */
    public boolean setActiveDevice(BluetoothDevice device, boolean hasFallbackDevice) {
        /* Clear active group */
        if (device == null) {
            setActiveGroupWithDevice(device, hasFallbackDevice);
            setActiveGroupWithDevice(device);
            return true;
        }
        if (getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
@@ -1211,7 +1207,7 @@ public class LeAudioService extends ProfileService {
        }
    }

    private void handleGroupTransitToInactive(int groupId, boolean hasFallbackDevice) {
    private void handleGroupTransitToInactive(int groupId) {
        synchronized (mGroupLock) {
            LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId);
            if (descriptor == null || !descriptor.mIsActive) {
@@ -1221,7 +1217,7 @@ public class LeAudioService extends ProfileService {

            descriptor.mIsActive = false;
            updateActiveDevices(groupId, descriptor.mDirection, AUDIO_DIRECTION_NONE,
                    descriptor.mIsActive, hasFallbackDevice);
                    descriptor.mIsActive);
            /* Clear lost devices */
            if (DBG) Log.d(TAG, "Clear for group: " + groupId);
            clearLostDevicesWhileStreaming(descriptor);
@@ -1394,8 +1390,9 @@ public class LeAudioService extends ProfileService {
            LeAudioGroupDescriptor descriptor = getGroupDescriptor(groupId);
            if (descriptor != null) {
                if (descriptor.mIsActive) {
                    descriptor.mIsActive = updateActiveDevices(
                            groupId, descriptor.mDirection, direction, descriptor.mIsActive);
                    descriptor.mIsActive =
                            updateActiveDevices(groupId, descriptor.mDirection, direction,
                            descriptor.mIsActive);
                    if (!descriptor.mIsActive) {
                        notifyGroupStatusChanged(groupId, BluetoothLeAudio.GROUP_STATUS_INACTIVE);
                    }
@@ -1425,7 +1422,7 @@ public class LeAudioService extends ProfileService {
                    break;
                }
                case LeAudioStackEvent.GROUP_STATUS_INACTIVE: {
                    handleGroupTransitToInactive(groupId, false);
                    handleGroupTransitToInactive(groupId);
                    break;
                }
                case LeAudioStackEvent.GROUP_STATUS_TURNED_IDLE_DURING_CALL: {
@@ -1650,12 +1647,14 @@ public class LeAudioService extends ProfileService {
        return result;
    }

    /**
     * Handles the connection of LE Audio device.
     *
     * @param device THe device that is connected.
     */
    public synchronized void deviceConnected(BluetoothDevice device) {
    @VisibleForTesting
    synchronized void connectionStateChanged(BluetoothDevice device, int fromState, int toState) {
        if ((device == null) || (fromState == toState)) {
            Log.e(TAG, "connectionStateChanged: unexpected invocation. device=" + device
                    + " fromState=" + fromState + " toState=" + toState);
            return;
        }
        if (toState == BluetoothProfile.STATE_CONNECTED) {
            int myGroupId = getGroupId(device);
            if (myGroupId == LE_AUDIO_GROUP_ID_INVALID
                    || getConnectedPeerDevices(myGroupId).size() == 1) {
@@ -1677,16 +1676,8 @@ public class LeAudioService extends ProfileService {
                mcpService.setDeviceAuthorized(device, true);
            }
        }

    /**
     * Handle the disconnection of LE Audio device.
     *
     * @param device The device that is disconnected
     * @param hasFallbackDevice whether it has fallback device when the {@code device}
     *                          is {@code null}.
     */
    public synchronized void deviceDisconnected(BluetoothDevice device, boolean hasFallbackDevice) {
        // If unbond, remove the state machine
        // Check if the device is disconnected - if unbond, remove the state machine
        if (toState == BluetoothProfile.STATE_DISCONNECTED) {
            int bondState = mAdapterService.getBondState(device);
            if (bondState == BluetoothDevice.BOND_NONE) {
                if (DBG) {
@@ -1725,8 +1716,7 @@ public class LeAudioService extends ProfileService {
                    updateActiveDevices(myGroupId,
                            descriptor.mDirection,
                            descriptor.mDirection,
                        descriptor.mIsActive,
                        hasFallbackDevice);
                            descriptor.mIsActive);
                    return;
                }
            }
@@ -1738,6 +1728,21 @@ public class LeAudioService extends ProfileService {
                        descriptor.mIsActive);
            }
        }
    }

    private class ConnectionStateChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED
                    .equals(intent.getAction())) {
                return;
            }
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int toState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
            int fromState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
            connectionStateChanged(device, fromState, toState);
        }
    }

    private synchronized boolean isSilentModeEnabled() {
        return mStoredRingerMode != AudioManager.RINGER_MODE_NORMAL;
+10 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static android.bluetooth.BluetoothGattCharacteristic.PROPERTY_READ;
import static android.bluetooth.BluetoothGattCharacteristic.PROPERTY_WRITE;
import static android.bluetooth.BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE;

import static java.util.Map.entry;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothDevice;
@@ -41,7 +43,9 @@ import android.os.Looper;
import android.util.Log;
import android.util.Pair;

import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.hearingaid.HearingAidService;
import com.android.bluetooth.le_audio.LeAudioService;
import com.android.internal.annotations.VisibleForTesting;

@@ -889,6 +893,12 @@ public class MediaControlGattService implements MediaControlGattServiceInterface
        }

        if (req.getOpcode() == Request.Opcodes.PLAY) {
            if (mAdapterService.getActiveDevices(BluetoothProfile.A2DP).size() > 0) {
                A2dpService.getA2dpService().setActiveDevice(null);
            }
            if (mAdapterService.getActiveDevices(BluetoothProfile.HEARING_AID).size() > 0) {
                HearingAidService.getHearingAidService().setActiveDevice(null);
            }
            if (mLeAudioService == null) {
                mLeAudioService = LeAudioService.getLeAudioService();
            }
Loading