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

Commit ca812392 authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Stop using intent from LE audio profile to ActiveDeviceManager

Bug: 289879962
Test: atest BluetoothInstrumentationTest
Change-Id: I749a1fbeba1ea016a5e6644543f7460f61e3624b
parent aa048a77
Loading
Loading
Loading
Loading
+29 −41
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.content.BroadcastReceiver;
@@ -68,12 +67,9 @@ import java.util.Set;
 *    devices is more than one, the rules below will apply.
 * 2) The selected A2DP active device is the one used for AVRCP as well.
 * 3) The HFP active device might be different from the A2DP active device.
 * 4) The Active Device Manager always listens for ACTION_ACTIVE_DEVICE_CHANGED
 *    broadcasts for each profile:
 *    - BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED for LE audio
 *    If such broadcast is received (e.g., triggered indirectly by user
 *    action on the UI), the device in the received broadcast is marked
 *    as the current active device for that profile.
 * 4) The Active Device Manager always listens for the change of active devices.
 *    When it changed (e.g., triggered indirectly by user action on the UI),
 *    the new active device is marked as the current active device for that profile.
 * 5) If there is a HearingAid active device, then A2DP, HFP and LE audio active devices
 *    must be set to null (i.e., A2DP, HFP and LE audio cannot have active devices).
 *    The reason is that A2DP, HFP or LE audio cannot be used together with HearingAid.
@@ -88,11 +84,8 @@ import java.util.Set;
 * 7) If the currently active device (per profile) is disconnected, the
 *    Active Device Manager just marks that the profile has no active device,
 *    and the lastly activated BT device that is still connected would be selected.
 * 8) If there is already an active device, and the corresponding
 *    ACTION_ACTIVE_DEVICE_CHANGED broadcast is received, the device
 *    contained in the broadcast is marked as active. However, if
 *    the contained device is null, the corresponding profile is marked
 *    as having no active device.
 * 8) If there is already an active device, however, if active device change notified
 *    with a null device, the corresponding profile is marked as having no active device.
 * 9) If a wired audio device is connected, the audio output is switched
 *    by the Audio Framework itself to that device. We detect this here,
 *    and the active device for each profile (A2DP/HFP/HearingAid/LE audio) is set
@@ -151,7 +144,6 @@ public class ActiveDeviceManager {
    private BluetoothDevice mClassicDeviceToBeActivated = null;
    private BluetoothDevice mClassicDeviceNotToBeActivated = null;

    // Broadcast receiver for all changes
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -168,32 +160,6 @@ public class ActiveDeviceManager {
            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                int currentState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
                mHandler.post(() -> handleAdapterStateChanged(currentState));
                return;
            }

            final BluetoothDevice device = intent.getParcelableExtra(
                    BluetoothDevice.EXTRA_DEVICE, BluetoothDevice.class);
            final int previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1);
            final int currentState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);

            if (currentState != -1 && previousState == currentState) {
                return;
            }

            switch (action) {
                case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
                    if (currentState == BluetoothProfile.STATE_CONNECTED) {
                        mHandler.post(() -> handleLeAudioConnected(device));
                    } else if (previousState == BluetoothProfile.STATE_CONNECTED) {
                        mHandler.post(() -> handleLeAudioDisconnected(device));
                    }
                    break;
                case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
                    mHandler.post(() -> handleLeAudioActiveDeviceChanged(device));
                    break;
                default:
                    Log.e(TAG, "Received unexpected intent, action=" + action);
                    break;
            }
        }
    };
@@ -246,6 +212,30 @@ public class ActiveDeviceManager {
        mHandler.post(() -> handleHfpActiveDeviceChanged(device));
    }

    /**
     * Called when LE audio connection state changed by LeAudioService
     *
     * @param device The device of which connection state was changed
     * @param prevState The previous connection state of the device
     * @param newState The new connection state of the device
     */
    public void leAudioConnectionStateChanged(BluetoothDevice device, int prevState, int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            mHandler.post(() -> handleLeAudioConnected(device));
        } else if (prevState == BluetoothProfile.STATE_CONNECTED) {
            mHandler.post(() -> handleLeAudioDisconnected(device));
        }
    }

    /**
     * Called when LE audio active state changed by LeAudioService
     *
     * @param device The device currently activated. {@code null} if no LE audio device activated
     */
    public void leAudioActiveStateChanged(BluetoothDevice device) {
        mHandler.post(() -> handleLeAudioActiveDeviceChanged(device));
    }

    /**
     * Called when HearingAid connection state changed by HearingAidService
     *
@@ -848,8 +838,6 @@ public class ActiveDeviceManager {
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        filter.addAction(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        mAdapterService.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);

        mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler);
+32 −0
Original line number Diff line number Diff line
@@ -1131,6 +1131,37 @@ public class LeAudioService extends ProfileService {
        return false;
    }

    /**
     * Send broadcast intent about LeAudio connection state changed. This is called by
     * LeAudioStateMachine.
     */
    void notifyConnectionStateChanged(BluetoothDevice device, int newState, int prevState) {
        if (DBG) {
            Log.d(
                    TAG,
                    "Notify connection state changed."
                            + device
                            + "("
                            + prevState
                            + " -> "
                            + newState
                            + ")");
        }

        mAdapterService
                .getActiveDeviceManager()
                .leAudioConnectionStateChanged(device, prevState, newState);
        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.addFlags(
                Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        Utils.sendBroadcast(
                this, intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions());
    }

    /**
     * Send broadcast intent about LeAudio active device.
     * This is called when AudioManager confirms, LeAudio device
@@ -1143,6 +1174,7 @@ public class LeAudioService extends ProfileService {
                    + ". Currently active device is " + mActiveAudioOutDevice);
        }

        mAdapterService.getActiveDeviceManager().leAudioActiveStateChanged(device);
        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+1 −13
Original line number Diff line number Diff line
@@ -47,15 +47,11 @@
package com.android.bluetooth.le_audio;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import static android.Manifest.permission.BLUETOOTH_CONNECT;

import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ProfileService;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.State;
@@ -514,15 +510,7 @@ final class LeAudioStateMachine extends StateMachine {
    private void broadcastConnectionState(int newState, int prevState) {
        log("Connection state " + mDevice + ": " + profileStateToString(prevState)
                    + "->" + profileStateToString(newState));

        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        Utils.sendBroadcast(mService, intent, BLUETOOTH_CONNECT,
                Utils.getTempAllowlistBroadcastOptions());
        mService.notifyConnectionStateChanged(mDevice, newState, prevState);
    }

    private static String messageWhatToString(int what) {
+5 −15
Original line number Diff line number Diff line
@@ -32,11 +32,9 @@ import static org.mockito.Mockito.when;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothSinkAudioPolicy;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.ArrayMap;
import android.util.SparseIntArray;
@@ -1249,11 +1247,8 @@ public class ActiveDeviceManagerTest {
    private void leAudioConnected(BluetoothDevice device) {
        mMostRecentDevice = device;

        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
        mActiveDeviceManager.leAudioConnectionStateChanged(
                device, BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.STATE_CONNECTED);
    }

    /**
@@ -1264,11 +1259,8 @@ public class ActiveDeviceManagerTest {
        mMostRecentDevice = (mDeviceConnectionStack.size() > 0)
                ? mDeviceConnectionStack.get(mDeviceConnectionStack.size() - 1) : null;

        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTED);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
        mActiveDeviceManager.leAudioConnectionStateChanged(
                device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED);
    }

    /**
@@ -1279,9 +1271,7 @@ public class ActiveDeviceManagerTest {
        mDeviceConnectionStack.add(device);
        mMostRecentDevice = device;

        Intent intent = new Intent(BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mActiveDeviceManager.getBroadcastReceiver().onReceive(mContext, intent);
        mActiveDeviceManager.leAudioActiveStateChanged(device);
    }

    /**
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.ActiveDeviceManager;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.bluetooth.btservice.storage.DatabaseManager;
@@ -109,6 +110,7 @@ public class LeAudioServiceTest {
    private BroadcastReceiver mLeAudioIntentReceiver;

    @Mock private AdapterService mAdapterService;
    @Mock private ActiveDeviceManager mActiveDeviceManager;
    @Mock private AudioManager mAudioManager;
    @Mock private DatabaseManager mDatabaseManager;
    @Mock private LeAudioNativeInterface mNativeInterface;
@@ -169,6 +171,7 @@ public class LeAudioServiceTest {
        doReturn(MAX_LE_AUDIO_CONNECTIONS).when(mAdapterService).getMaxConnectedAudioDevices();
        doReturn(new ParcelUuid[]{BluetoothUuid.LE_AUDIO}).when(mAdapterService)
                .getRemoteUuids(any(BluetoothDevice.class));
        doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager();
        doReturn(mDatabaseManager).when(mAdapterService).getDatabase();
        doReturn(true, false).when(mAdapterService).isStartedProfile(anyString());

Loading