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

Commit 21c606da authored by Rongxuan Liu's avatar Rongxuan Liu Committed by Gerrit Code Review
Browse files

Merge changes I02c57178,I7a2ae680 into main

* changes:
  LeAudioService: Destroy broadcast if it fails to start in time
  flags: add leaudio_broadcast_destroy_after_timeout
parents a309b709 dbfaa5b5
Loading
Loading
Loading
Loading
+16 −35
Original line number Diff line number Diff line
@@ -2607,6 +2607,11 @@ public class LeAudioService extends ProfileService {
    void transitionFromBroadcastToUnicast() {
        if (mUnicastGroupIdDeactivatedForBroadcastTransition == LE_AUDIO_GROUP_ID_INVALID) {
            Log.d(TAG, "No deactivated group due for broadcast transmission");
            // Notify audio manager
            if (mBroadcastDescriptors.values().stream()
                    .noneMatch(d -> d.mState.equals(LeAudioStackEvent.BROADCAST_STATE_STREAMING))) {
                updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
            }
            return;
        }

@@ -3031,22 +3036,7 @@ public class LeAudioService extends ProfileService {
                    notifyPlaybackStopped(broadcastId,
                            BluetoothStatusCodes.REASON_LOCAL_APP_REQUEST);


                    /* Restore the Unicast stream from before the Broadcast was started. */
                    if (mUnicastGroupIdDeactivatedForBroadcastTransition
                            != LE_AUDIO_GROUP_ID_INVALID) {
                    transitionFromBroadcastToUnicast();
                    } else {
                        // Notify audio manager
                        if (mBroadcastDescriptors.values().stream()
                                .noneMatch(
                                        d ->
                                                d.mState.equals(
                                                        LeAudioStackEvent
                                                                .BROADCAST_STATE_STREAMING))) {
                            updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                        }
                    }
                    destroyBroadcast(broadcastId);
                    break;
                case LeAudioStackEvent.BROADCAST_STATE_CONFIGURING:
@@ -3068,21 +3058,7 @@ public class LeAudioService extends ProfileService {
                        bassClientService.suspendReceiversSourceSynchronization(broadcastId);
                    }

                    /* Restore the Unicast stream from before the Broadcast was started. */
                    if (mUnicastGroupIdDeactivatedForBroadcastTransition
                            != LE_AUDIO_GROUP_ID_INVALID) {
                    transitionFromBroadcastToUnicast();
                    } else {
                        // Notify audio manager
                        if (mBroadcastDescriptors.values().stream()
                                .noneMatch(
                                        d ->
                                                d.mState.equals(
                                                        LeAudioStackEvent
                                                                .BROADCAST_STATE_STREAMING))) {
                            updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                        }
                    }
                    break;
                case LeAudioStackEvent.BROADCAST_STATE_STOPPING:
                    Log.d(TAG, "Broadcast broadcastId: " + broadcastId + " stopping.");
@@ -4382,6 +4358,10 @@ public class LeAudioService extends ProfileService {
                return;
            }

            if (Flags.leaudioBroadcastDestroyAfterTimeout()) {
                transitionFromBroadcastToUnicast();
                destroyBroadcast(mBroadcastId);
            } else {
                if (mActiveBroadcastAudioDevice != null) {
                    updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                }
@@ -4389,6 +4369,7 @@ public class LeAudioService extends ProfileService {
                notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT);
            }
        }
    }

    /**
     * Binder object: must be a static class or memory leak may occur
+56 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
public class LeAudioBroadcastServiceTest {
    private static final int TIMEOUT_MS = 1000;
    private static final int CREATE_BROADCAST_TIMEOUT_MS = 6000;

    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

@@ -430,6 +431,61 @@ public class LeAudioBroadcastServiceTest {
        Assert.assertTrue(mOnBroadcastStartFailedCalled);
    }

    @Test
    public void testCreateBroadcastTimeout() {
        mSetFlagsRule.enableFlags(Flags.FLAG_LEAUDIO_BROADCAST_DESTROY_AFTER_TIMEOUT);

        int broadcastId = 243;
        byte[] code = {0x00, 0x01, 0x00, 0x02};

        mService.mBroadcastCallbacks.register(mCallbacks);

        BluetoothLeAudioContentMetadata.Builder meta_builder =
                new BluetoothLeAudioContentMetadata.Builder();
        meta_builder.setLanguage("deu");
        meta_builder.setProgramInfo("Public broadcast info");
        BluetoothLeAudioContentMetadata meta = meta_builder.build();
        BluetoothLeBroadcastSettings settings = buildBroadcastSettingsFromMetadata(meta, code, 1);
        mService.createBroadcast(settings);

        // Test data with only one subgroup
        int[] expectedQualityArray = {settings.getSubgroupSettings().get(0).getPreferredQuality()};
        byte[][] expectedDataArray = {
            settings.getSubgroupSettings().get(0).getContentMetadata().getRawMetadata()
        };

        verify(mLeAudioBroadcasterNativeInterface, times(1))
                .createBroadcast(
                        eq(true),
                        eq(TEST_BROADCAST_NAME),
                        eq(code),
                        eq(settings.getPublicBroadcastMetadata().getRawMetadata()),
                        eq(expectedQualityArray),
                        eq(expectedDataArray));

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

        // Verify if broadcast is auto-started on start
        verify(mLeAudioBroadcasterNativeInterface, times(1)).startBroadcast(eq(broadcastId));
        Assert.assertTrue(mOnBroadcastStartedCalled);

        // Notify initial paused state
        LeAudioStackEvent state_event =
                new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_BROADCAST_STATE);
        state_event.valueInt1 = broadcastId;
        state_event.valueInt2 = LeAudioStackEvent.BROADCAST_STATE_PAUSED;
        mService.messageFromNative(state_event);

        // Check if broadcast is destroyed after timeout
        verify(mLeAudioBroadcasterNativeInterface, timeout(CREATE_BROADCAST_TIMEOUT_MS).times(1))
                .destroyBroadcast(eq(broadcastId));
    }

    @Test
    public void testCreateBroadcast_updateQualityToStandard() {
        byte[] code = {0x00, 0x01, 0x00, 0x02};
+11 −1
Original line number Diff line number Diff line
@@ -289,3 +289,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "leaudio_broadcast_destroy_after_timeout"
    namespace: "bluetooth"
    description: "Destroy broadcast if it fails to start in time"
    bug: "332500141"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}