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

Commit b4585a92 authored by Stanley Tng's avatar Stanley Tng
Browse files

Fix the volume of A2DP devices which switching audio

When switching audio between Hearing Aids and A2DP devices, the stored
volume may be incorrect due to a race condition with the audio service.
This CL will only stored the A2DP when switching away from A2DP and also
before the audio service starts its processing.

Bug: 123720932
Test: Manual test with switching between Hearing Aids and A2DP speaker
Change-Id: I634ab58f6103197e7a99301b1e9f4d28e55e35a5
parent fa7070cb
Loading
Loading
Loading
Loading
+26 −4
Original line number Original line Diff line number Diff line
@@ -495,6 +495,24 @@ public class A2dpService extends ProfileService {
        return true;
        return true;
    }
    }


    /**
     * Early notification that Hearing Aids will be the active device. This allows the A2DP to save
     * its volume before the Audio Service starts changing its media stream.
     */
    public void earlyNotifyHearingAidActive() {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");

        synchronized (mStateMachines) {
            if ((mActiveDevice != null) && (AvrcpTargetService.get() != null)) {
                // Switch active device from A2DP to Hearing Aids.
                if (DBG) {
                    Log.d(TAG, "earlyNotifyHearingAidActive: Save volume for " + mActiveDevice);
                }
                AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice);
            }
        }
    }

    /**
    /**
     * Set the active device.
     * Set the active device.
     *
     *
@@ -534,6 +552,14 @@ public class A2dpService extends ProfileService {
            codecStatus = sm.getCodecStatus();
            codecStatus = sm.getCodecStatus();


            boolean deviceChanged = !Objects.equals(device, mActiveDevice);
            boolean deviceChanged = !Objects.equals(device, mActiveDevice);
            if ((AvrcpTargetService.get() != null) && (mActiveDevice != null) && deviceChanged) {
                // Switch from one A2DP to another A2DP device
                if (DBG) {
                    Log.d(TAG, "Switch A2DP devices to " + device + " from " + mActiveDevice);
                }
                AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice);
            }

            // This needs to happen before we inform the audio manager that the device
            // This needs to happen before we inform the audio manager that the device
            // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
            // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why.
            updateAndBroadcastActiveDevice(device);
            updateAndBroadcastActiveDevice(device);
@@ -875,10 +901,6 @@ public class A2dpService extends ProfileService {


        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
            if (AvrcpTargetService.get() != null) {
            if (AvrcpTargetService.get() != null) {
                if (mActiveDevice != null) {
                    AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice);
                }

                AvrcpTargetService.get().volumeDeviceSwitched(device);
                AvrcpTargetService.get().volumeDeviceSwitched(device);
            }
            }


+17 −0
Original line number Original line Diff line number Diff line
@@ -33,9 +33,11 @@ import android.util.StatsLog;


import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.Utils;
import com.android.bluetooth.Utils;
import com.android.bluetooth.a2dp.A2dpService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -75,6 +77,8 @@ public class HearingAidService extends ProfileService {
    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;


    private final ServiceFactory mFactory = new ServiceFactory();

    @Override
    @Override
    protected IProfileServiceBinder initBinder() {
    protected IProfileServiceBinder initBinder() {
        return new BluetoothHearingAidBinder(this);
        return new BluetoothHearingAidBinder(this);
@@ -608,6 +612,19 @@ public class HearingAidService extends ProfileService {


        StatsLog.write(StatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothProfile.HEARING_AID,
        StatsLog.write(StatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothProfile.HEARING_AID,
                mAdapterService.obfuscateAddress(device));
                mAdapterService.obfuscateAddress(device));

        if (device != null) {
            // Give an early notification to A2DP that active device is being switched
            // to Hearing Aids before the Audio Service.
            final A2dpService a2dpService = mFactory.getA2dpService();
            if (a2dpService != null) {
                if (DBG) {
                    Log.d(TAG, "earlyNotifyHearingAidActive for " + device);
                }
                a2dpService.earlyNotifyHearingAidActive();
            }
        }

        Intent intent = new Intent(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
        Intent intent = new Intent(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT