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

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

Merge changes I52f85c3f,I759c0e57 into main

* changes:
  AudioService: new SCO audio connection management
  AudioService: new headset profile management
parents d3e4c280 ec6a8de1
Loading
Loading
Loading
Loading
+39 −23
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();
    }

@@ -400,7 +413,7 @@ public class AudioDeviceBroker {
        if (client == null) {
            return;
        }

        if (!mScoManagedByAudio) {
            boolean isBtScoRequested = isBluetoothScoRequested();
            if (isBtScoRequested && (!wasBtScoRequested || !isBluetoothScoActive())) {
                if (!mBtHelper.startBluetoothSco(scoAudioMode, eventSource)) {
@@ -417,7 +430,7 @@ public class AudioDeviceBroker {
            } else if (!isBtScoRequested && wasBtScoRequested) {
                mBtHelper.stopBluetoothSco(eventSource);
            }

        }
        // In BT classic for communication, the device changes from a2dp to sco device, but for
        // LE Audio it stays the same and we must trigger the proper stream volume alignment, if
        // LE Audio communication device is activated after the audio system has already switched to
@@ -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");
                                }
                            }
@@ -2511,7 +2526,7 @@ public class AudioDeviceBroker {
            setCommunicationRouteForClient(crc.getBinder(), crc.getUid(), crc.getDevice(),
                    BtHelper.SCO_MODE_UNDEFINED, crc.isPrivileged(), eventSource);
        } else {
            if (!isBluetoothScoRequested() && wasBtScoRequested) {
            if (!mScoManagedByAudio && !isBluetoothScoRequested() && wasBtScoRequested) {
                mBtHelper.stopBluetoothSco(eventSource);
            }
            updateCommunicationRoute(eventSource);
@@ -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);
@@ -4529,11 +4532,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());
    }
@@ -7859,7 +7863,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);
        }
+58 −42
Original line number Diff line number Diff line
@@ -401,6 +401,22 @@ public class BtHelper {
    private void onScoAudioStateChanged(int state) {
        boolean broadcast = false;
        int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
        if (mDeviceBroker.isScoManagedByAudio()) {
            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) {
                case BluetoothHeadset.STATE_AUDIO_CONNECTED:
                    scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
@@ -446,6 +462,7 @@ public class BtHelper {
                default:
                    break;
            }
        }
        if (broadcast) {
            broadcastScoConnectionState(scoAudioState);
            //FIXME: this is to maintain compatibility with deprecated intent
@@ -454,7 +471,6 @@ public class BtHelper {
            newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
            sendStickyBroadcastToAll(newIntent);
        }

    }
    /**
     *