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

Commit 2d1deafb authored by Rongxuan Liu's avatar Rongxuan Liu Committed by Automerger Merge Worker
Browse files

Merge "le_audio: Introduce broadcast audio session created event" into main...

Merge "le_audio: Introduce broadcast audio session created event" into main am: e9157ecf am: 2824a067

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/3139473



Change-Id: I8b649d433b7c221e9fc883da9dd749896685ee5b
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 9e338a66 2824a067
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -721,6 +721,7 @@ static jmethodID method_onBroadcastCreated;
static jmethodID method_onBroadcastDestroyed;
static jmethodID method_onBroadcastStateChanged;
static jmethodID method_onBroadcastMetadataChanged;
static jmethodID method_onBroadcastAudioSessionCreated;

static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
static std::shared_timed_mutex sBroadcasterInterfaceMutex;
@@ -1132,6 +1133,19 @@ public:
    sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastMetadataChanged,
                                 (jint)broadcast_id, metadata_obj.get());
  }

  void OnBroadcastAudioSessionCreated(bool success) override {
    log::info("");

    std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
    CallbackEnv sCallbackEnv(__func__);

    if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
      return;
    }
    sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastAudioSessionCreated,
                                 success ? JNI_TRUE : JNI_FALSE);
  }
};

static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
@@ -1449,6 +1463,7 @@ static int register_com_android_bluetooth_le_audio_broadcaster(JNIEnv* env) {
          {"onBroadcastStateChanged", "(II)V", &method_onBroadcastStateChanged},
          {"onBroadcastMetadataChanged", "(ILandroid/bluetooth/BluetoothLeBroadcastMetadata;)V",
           &method_onBroadcastMetadataChanged},
          {"onBroadcastAudioSessionCreated", "(Z)V", &method_onBroadcastAudioSessionCreated},
  };
  GET_JAVA_METHODS(env, "com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface",
                   javaMethods);
+10 −0
Original line number Diff line number Diff line
@@ -131,6 +131,16 @@ public class LeAudioBroadcasterNativeInterface {
        sendMessageToService(event);
    }

    @VisibleForTesting
    public void onBroadcastAudioSessionCreated(boolean success) {
        Log.d(TAG, "onBroadcastAudioSessionCreated: success=" + success);
        LeAudioStackEvent event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED);

        event.valueBool1 = success;
        sendMessageToService(event);
    }

    /**
     * Initializes the native interface.
     *
+67 −28
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ public class LeAudioService extends ProfileService {
    private final LinkedList<BluetoothLeBroadcastSettings> mCreateBroadcastQueue =
            new LinkedList<>();
    boolean mIsSourceStreamMonitorModeEnabled = false;
    boolean mIsSinkStreamMonitorModeEnabled = false;
    boolean mIsBroadcastPausedFromOutside = false;

    @VisibleForTesting TbsService mTbsService;
@@ -528,6 +529,7 @@ public class LeAudioService extends ProfileService {
        mCreateBroadcastQueue.clear();
        mAwaitingBroadcastCreateResponse = false;
        mIsSourceStreamMonitorModeEnabled = false;
        mIsSinkStreamMonitorModeEnabled = false;
        mIsBroadcastPausedFromOutside = false;

        clearBroadcastTimeoutCallback();
@@ -1053,8 +1055,9 @@ public class LeAudioService extends ProfileService {
            return;
        }

        if (!leaudioBigDependsOnAudioState()) {
            if (!areAllGroupsInNotActiveState()) {
            /* Broadcast would be created once unicast group became inactive */
                /* Broadcast will be created once unicast group became inactive */
                Log.i(
                        TAG,
                        "Unicast group is active, queueing Broadcast creation, while the Unicast"
@@ -1067,6 +1070,7 @@ public class LeAudioService extends ProfileService {

                return;
            }
        }

        byte[] broadcastCode = broadcastSettings.getBroadcastCode();
        boolean isEncrypted = (broadcastCode != null) && (broadcastCode.length != 0);
@@ -1090,6 +1094,9 @@ public class LeAudioService extends ProfileService {
        Log.i(TAG, "createBroadcast: isEncrypted=" + (isEncrypted ? "true" : "false"));

        mAwaitingBroadcastCreateResponse = true;
        if (leaudioBigDependsOnAudioState()) {
            mCreateBroadcastQueue.add(broadcastSettings);
        }
        mLeAudioBroadcasterNativeInterface.createBroadcast(
                broadcastSettings.isPublicBroadcast(),
                broadcastSettings.getBroadcastName(),
@@ -1293,6 +1300,7 @@ public class LeAudioService extends ProfileService {

        Log.d(TAG, "destroyBroadcast");
        if (Flags.leaudioBroadcastAudioHandoverPolicies()) {
            mIsSinkStreamMonitorModeEnabled = false;
            mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false);
        }
        mLeAudioBroadcasterNativeInterface.destroyBroadcast(broadcastId);
@@ -2062,16 +2070,6 @@ public class LeAudioService extends ProfileService {
                newDevice, previousDevice, getBroadcastProfile(suppressNoisyIntent));
    }

    /*
     * Listen mode is set when broadcast is queued, waiting for create response notification or
     * descriptor was created - idicate that create notification was received.
     */
    private boolean wasSetSinkListeningMode() {
        return !mCreateBroadcastQueue.isEmpty()
                || mAwaitingBroadcastCreateResponse
                || !mBroadcastDescriptors.isEmpty();
    }

    /**
     * Report the active devices change to the active device manager and the media framework.
     *
@@ -2107,7 +2105,9 @@ public class LeAudioService extends ProfileService {
            if (notifyAndUpdateInactiveOutDeviceOnly
                    && ((newSupportedAudioDirections & AUDIO_DIRECTION_INPUT_BIT) != 0)) {
                newInDevice = getLeadDeviceForTheGroup(groupId);
            } else if (Flags.leaudioBroadcastAudioHandoverPolicies() && wasSetSinkListeningMode()) {
            } else if (Flags.leaudioBroadcastAudioHandoverPolicies()
                    && mIsSinkStreamMonitorModeEnabled) {
                mIsSinkStreamMonitorModeEnabled = false;
                mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, false);
            }
        }
@@ -2716,6 +2716,7 @@ public class LeAudioService extends ProfileService {
        if (bassClientService == null) {
            Log.e(TAG, "handleSourceStreamStatusChange: BASS Client service is not available");

            mIsSourceStreamMonitorModeEnabled = false;
            mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SOURCE, false);
        }

@@ -3502,6 +3503,11 @@ public class LeAudioService extends ProfileService {
                                mBroadcastIdDeactivatedForUnicastTransition = Optional.empty();
                            }

                            if (leaudioBigDependsOnAudioState()) {
                                if (mAwaitingBroadcastCreateResponse) {
                                    updateFallbackUnicastGroupIdForBroadcast(groupId);
                                }
                            } else {
                                if (!mCreateBroadcastQueue.isEmpty()) {
                                    updateFallbackUnicastGroupIdForBroadcast(groupId);
                                    BluetoothLeBroadcastSettings settings =
@@ -3509,6 +3515,7 @@ public class LeAudioService extends ProfileService {
                                    createBroadcast(settings);
                                }
                            }
                        }
                        break;
                    }
                case LeAudioStackEvent.GROUP_STATUS_TURNED_IDLE_DURING_CALL:
@@ -3528,6 +3535,11 @@ public class LeAudioService extends ProfileService {
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED) {
            int broadcastId = stackEvent.valueInt1;
            boolean success = stackEvent.valueBool1;

            if (leaudioBigDependsOnAudioState()) {
                mCreateBroadcastQueue.remove();
            }

            if (success) {
                Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " created.");
                mBroadcastDescriptors.put(broadcastId, new LeAudioBroadcastDescriptor());
@@ -3722,6 +3734,33 @@ public class LeAudioService extends ProfileService {
                                notifyBroadcastMetadataChanged(
                                        broadcastId, stackEvent.broadcastMetadata));
            }
        } else if (stackEvent.type
                == LeAudioStackEvent.EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED) {
            boolean success = stackEvent.valueBool1;

            if (!success) {
                Log.e(TAG, "EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED: failed to create");

                if (mAwaitingBroadcastCreateResponse) {
                    mAwaitingBroadcastCreateResponse = false;
                    mCreateBroadcastQueue.clear();
                }

                return;
            }

            /* Broadcast creation procedure were initiated and some unicast group are still
             * active.
             */
            if (mAwaitingBroadcastCreateResponse && !areAllGroupsInNotActiveState()) {
                /* Broadcast would be created once unicast group became inactive */
                Log.i(TAG, "Unicast group is active, deactivate due to pending broadcast");
                if (Flags.leaudioBroadcastAudioHandoverPolicies()) {
                    mIsSinkStreamMonitorModeEnabled = true;
                    mNativeInterface.setUnicastMonitorMode(LeAudioStackEvent.DIRECTION_SINK, true);
                }
                removeActiveDevice(true);
            }
        } else if (stackEvent.type == LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED) {
            mLeAudioNativeIsInitialized = true;
            for (Map.Entry<ParcelUuid, Pair<Integer, Integer>> entry :
+5 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ public class LeAudioStackEvent {
    public static final int EVENT_TYPE_BROADCAST_DESTROYED = EVENT_TYPE_UNICAST_MAX + 2;
    public static final int EVENT_TYPE_BROADCAST_STATE = EVENT_TYPE_UNICAST_MAX + 3;
    public static final int EVENT_TYPE_BROADCAST_METADATA_CHANGED = EVENT_TYPE_UNICAST_MAX + 4;
    public static final int EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED = EVENT_TYPE_UNICAST_MAX + 5;

    // Do not modify without updating the HAL bt_le_audio.h files.
    // Match up with GroupStatus enum of bt_le_audio.h
@@ -178,6 +179,8 @@ public class LeAudioStackEvent {
                return "EVENT_TYPE_BROADCAST_STATE";
            case EVENT_TYPE_BROADCAST_METADATA_CHANGED:
                return "EVENT_TYPE_BROADCAST_METADATA_CHANGED";
            case EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED:
                return "EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED";
            case EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED:
                return "EVENT_TYPE_AUDIO_LOCAL_CODEC_CONFIG_CAPA_CHANGED";
            case EVENT_TYPE_AUDIO_GROUP_CURRENT_CODEC_CONFIG_CHANGED:
@@ -364,6 +367,8 @@ public class LeAudioStackEvent {

    private static String eventTypeValueBool1ToString(int type, boolean value) {
        switch (type) {
            case EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED:
                // same as EVENT_TYPE_BROADCAST_CREATED
            case EVENT_TYPE_BROADCAST_CREATED:
                return "{success:" + value + "}";
            default:
+29 −8
Original line number Diff line number Diff line
@@ -795,17 +795,19 @@ public class LeAudioBroadcastServiceTest {
    @Test
    public void testCreatePendingBroadcast() {
        int groupId = 1;
        int broadcastId = 243;
        byte[] code = {0x00, 0x01, 0x00, 0x02};

        mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE);

        prepareConnectedUnicastDevice(groupId);

        LeAudioStackEvent create_event =
        LeAudioStackEvent stackEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
        create_event.valueInt1 = groupId;
        create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE;
        mService.messageFromNative(create_event);
        stackEvent.valueInt1 = groupId;
        stackEvent.valueInt2 = LeAudioStackEvent.GROUP_STATUS_ACTIVE;
        mService.messageFromNative(stackEvent);

        /* Prepare create broadcast */
        BluetoothLeAudioContentMetadata.Builder meta_builder =
@@ -817,15 +819,27 @@ public class LeAudioBroadcastServiceTest {
        BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1);
        mService.createBroadcast(settings);

        /* Successfully created audio session notification */
        stackEvent =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED);
        stackEvent.valueBool1 = true;
        mService.messageFromNative(stackEvent);

        /* Check if broadcast is started automatically when created */
        stackEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_CREATED);
        stackEvent.valueInt1 = broadcastId;
        stackEvent.valueBool1 = true;
        mService.messageFromNative(stackEvent);

        /* Active group should become inactive */
        int activeGroup = mService.getActiveGroupId();
        Assert.assertEquals(activeGroup, LE_AUDIO_GROUP_ID_INVALID);

        /* Imitate group inactivity to cause create broadcast */
        create_event = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
        create_event.valueInt1 = groupId;
        create_event.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE;
        mService.messageFromNative(create_event);
        stackEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_GROUP_STATUS_CHANGED);
        stackEvent.valueInt1 = groupId;
        stackEvent.valueInt2 = LeAudioStackEvent.GROUP_STATUS_INACTIVE;
        mService.messageFromNative(stackEvent);

        List<BluetoothLeBroadcastSubgroupSettings> settingsList = settings.getSubgroupSettings();

@@ -886,6 +900,7 @@ public class LeAudioBroadcastServiceTest {
    private void prepareHandoverStreamingBroadcast(int groupId, int broadcastId, byte[] code) {
        mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_ROUTING_CENTRALIZATION);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_AUDIO_HANDOVER_POLICIES);
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE);

        synchronized (mService.mBroadcastCallbacks) {
            mService.mBroadcastCallbacks.register(mCallbacks);
@@ -919,6 +934,12 @@ public class LeAudioBroadcastServiceTest {
        BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1);
        mService.createBroadcast(settings);

        /* Successfully created audio session notification */
        create_event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_AUDIO_SESSION_CREATED);
        create_event.valueBool1 = true;
        mService.messageFromNative(create_event);

        verify(mAudioManager, times(1))
                .handleBluetoothActiveDeviceChanged(
                        eq(mBroadcastDevice), eq(null), any(BluetoothProfileConnectionInfo.class));
Loading