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

Commit d12e2e01 authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioService: new headset profile management

Align BT Headset profile management with other profiles:
do not use intents for device connection indication but use
AudioManager.handleBluetoothActiveDeviceChanged()

Test: make
Bug: 265057196
Flag: android.media.audio.sco_managed_by_audio
Change-Id: I759c0e57b988aafbb63af9d4469e4c2206a2976d
parent 9a9a9cb8
Loading
Loading
Loading
Loading
+23 −7
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.audio;

import static android.media.audio.Flags.scoManagedByAudio;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
@@ -54,6 +56,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.sysprop.BluetoothProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -74,7 +77,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * @hide
 * (non final for mocking/spying)
@@ -167,6 +169,15 @@ public class AudioDeviceBroker {
    @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
    public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L;

    /** Indicates if headset profile connection and SCO audio control use the new implementation
     * aligned with other BT profiles. True if both the feature flag Flags.scoManagedByAudio() and
     * the system property audio.sco.managed.by.audio are true.
     */
    private final boolean mScoManagedByAudio;
    /*package*/ boolean isScoManagedByAudio() {
        return mScoManagedByAudio;
    }

    //-------------------------------------------------------------------
    /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service,
            @NonNull AudioSystemAdapter audioSystem) {
@@ -176,7 +187,8 @@ public class AudioDeviceBroker {
        mDeviceInventory = new AudioDeviceInventory(this);
        mSystemServer = SystemServerAdapter.getDefaultAdapter(mContext);
        mAudioSystem = audioSystem;

        mScoManagedByAudio = scoManagedByAudio()
                && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false);
        init();
    }

@@ -192,7 +204,8 @@ public class AudioDeviceBroker {
        mDeviceInventory = mockDeviceInventory;
        mSystemServer = mockSystemServer;
        mAudioSystem = audioSystem;

        mScoManagedByAudio = scoManagedByAudio()
                && BluetoothProperties.isScoManagedByAudioEnabled().orElse(false);
        init();
    }

@@ -1685,6 +1698,8 @@ public class AudioDeviceBroker {

        pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner);

        pw.println("\n" + prefix + "mScoManagedByAudio: " + mScoManagedByAudio);

        mBtHelper.dump(pw, prefix);
    }

@@ -1837,10 +1852,10 @@ public class AudioDeviceBroker {
                                            ? mAudioService.getBluetoothContextualVolumeStream()
                                            : AudioSystem.STREAM_DEFAULT);
                                if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
                                        || btInfo.mProfile
                                        == BluetoothProfile.HEARING_AID) {
                                    onUpdateCommunicationRouteClient(
                                            isBluetoothScoRequested(),
                                        || btInfo.mProfile == BluetoothProfile.HEARING_AID
                                        || (mScoManagedByAudio
                                            && btInfo.mProfile == BluetoothProfile.HEADSET)) {
                                    onUpdateCommunicationRouteClient(isBluetoothScoRequested(),
                                            "setBluetoothActiveDevice");
                                }
                            }
@@ -2815,4 +2830,5 @@ public class AudioDeviceBroker {
    void clearDeviceInventory() {
        mDeviceInventory.clearDeviceInventory();
    }

}
+9 −0
Original line number Diff line number Diff line
@@ -859,6 +859,15 @@ public class AudioDeviceInventory {
                                btInfo, streamType, codec, "onSetBtActiveDevice");
                    }
                    break;
                case BluetoothProfile.HEADSET:
                    if (mDeviceBroker.isScoManagedByAudio()) {
                        if (switchToUnavailable) {
                            mDeviceBroker.onSetBtScoActiveDevice(null);
                        } else if (switchToAvailable) {
                            mDeviceBroker.onSetBtScoActiveDevice(btInfo.mDevice);
                        }
                    }
                    break;
                default: throw new IllegalArgumentException("Invalid profile "
                                 + BluetoothProfile.getProfileName(btInfo.mProfile));
            }
+8 −3
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
import static android.media.audio.Flags.focusFreezeTestApi;
import static android.media.audio.Flags.roForegroundAudioControl;
import static android.media.audio.Flags.scoManagedByAudio;
import static android.media.audiopolicy.Flags.enableFadeManagerConfiguration;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.INVALID_UID;
@@ -1503,7 +1504,9 @@ public class AudioService extends IAudioService.Stub
        // Register for device connection intent broadcasts.
        IntentFilter intentFilter =
                new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        if (!mDeviceBroker.isScoManagedByAudio()) {
            intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
        }
        intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
        if (mDisplayManager == null) {
            intentFilter.addAction(Intent.ACTION_SCREEN_ON);
@@ -4528,11 +4531,12 @@ public class AudioService extends IAudioService.Stub
                + focusFreezeTestApi());
        pw.println("\tcom.android.media.audio.disablePrescaleAbsoluteVolume:"
                + disablePrescaleAbsoluteVolume());
        pw.println("\tcom.android.media.audio.setStreamVolumeOrder:"
                + setStreamVolumeOrder());
        pw.println("\tandroid.media.audio.roForegroundAudioControl:"
                + roForegroundAudioControl());
        pw.println("\tandroid.media.audio.scoManagedByAudio:"
                + scoManagedByAudio());
        pw.println("\tcom.android.media.audio.vgsVssSyncMuteOrder:"
                + vgsVssSyncMuteOrder());
    }
@@ -7858,7 +7862,8 @@ public class AudioService extends IAudioService.Stub
        if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
                && profile != BluetoothProfile.LE_AUDIO
                && profile != BluetoothProfile.LE_AUDIO_BROADCAST
                && profile != BluetoothProfile.HEARING_AID) {
                && profile != BluetoothProfile.HEARING_AID
                && !(mDeviceBroker.isScoManagedByAudio() && profile == BluetoothProfile.HEADSET)) {
            throw new IllegalArgumentException("Illegal BluetoothProfile profile for device "
                    + previousDevice + " -> " + newDevice + ". Got: " + profile);
        }