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

Commit a3eefca8 authored by Grzegorz Kołodziejczyk's avatar Grzegorz Kołodziejczyk Committed by Rongxuan Liu
Browse files

broadcast: Remove redundant broadcast start

Since Audio Framework driven BIG creation was introduced, there is no
need for external call for starting broadacst. Broadcast start is now
driven by Audio Framework callbacks.

Bug: 369554930
Bug: 347204335
Test: atest LeAudioBroadcastServiceTest
Test: atest bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine
Flag: leaudio_big_depends_on_audio_state
Change-Id: I02db58b85f1f117115845431ed7990cab4328554
parent d0e8bb0d
Loading
Loading
Loading
Loading
+125 −72
Original line number Diff line number Diff line
@@ -117,6 +117,9 @@ public class LeAudioService extends ProfileService {
    // Timeout for state machine thread join, to prevent potential ANR.
    private static final int SM_THREAD_JOIN_TIMEOUT_MS = 1000;

    /* 5 seconds timeout for Broadcast streaming state transition */
    private static final int CREATE_BROADCAST_TIMEOUT_MS = 5000;

    private static LeAudioService sLeAudioService;

    /** Indicates group audio support for none direction */
@@ -151,9 +154,6 @@ public class LeAudioService extends ProfileService {
                    .setSampleRate(BluetoothLeAudioCodecConfig.SAMPLE_RATE_48000)
                    .build();

    /* 5 seconds timeout for Broadcast streaming state transition */
    private static final int DIALING_OUT_TIMEOUT_MS = 5000;

    private AdapterService mAdapterService;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
@@ -165,6 +165,8 @@ public class LeAudioService extends ProfileService {
    private final ReentrantReadWriteLock mGroupReadWriteLock = new ReentrantReadWriteLock();
    private final Lock mGroupReadLock = mGroupReadWriteLock.readLock();
    private final Lock mGroupWriteLock = mGroupReadWriteLock.writeLock();
    private CreateBroadcastTimeoutEvent mCreateBroadcastTimeoutEvent;

    ServiceFactory mServiceFactory = new ServiceFactory();

    private final LeAudioNativeInterface mNativeInterface;
@@ -182,7 +184,6 @@ public class LeAudioService extends ProfileService {
    BluetoothDevice mLeAudioDeviceInactivatedForHfpHandover = null;

    LeAudioBroadcasterNativeInterface mLeAudioBroadcasterNativeInterface = null;
    private DialingOutTimeoutEvent mDialingOutTimeoutEvent = null;
    @VisibleForTesting AudioManager mAudioManager;
    LeAudioTmapGattServer mTmapGattServer;
    int mTmapRoleMask;
@@ -653,7 +654,7 @@ public class LeAudioService extends ProfileService {
        mIsSinkStreamMonitorModeEnabled = false;
        mIsBroadcastPausedFromOutside = false;

        clearBroadcastTimeoutCallback();
        clearCreateBroadcastTimeoutCallback();

        if (!Flags.leaudioSynchronizeStart()) {
            mHandler.removeCallbacks(this::init);
@@ -1148,29 +1149,48 @@ public class LeAudioService extends ProfileService {
        return LE_AUDIO_GROUP_ID_INVALID;
    }

    /**
     * Creates LeAudio Broadcast instance with BluetoothLeBroadcastSettings.
     *
     * @param broadcastSettings broadcast settings for this broadcast source
     */
    public void createBroadcast(BluetoothLeBroadcastSettings broadcastSettings) {
    private int canBroadcastBeCreated(BluetoothLeBroadcastSettings broadcastSettings) {
        if (mBroadcastDescriptors.size() >= getMaximumNumberOfBroadcasts()) {
            Log.w(
                    TAG,
                    "createBroadcast reached maximum allowed broadcasts number: "
                            + getMaximumNumberOfBroadcasts());
            mHandler.post(
                    () ->
                            notifyBroadcastStartFailed(
                                    BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES));
            return;
            return BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES;
        }

        byte[] broadcastCode = broadcastSettings.getBroadcastCode();
        if (broadcastCode != null && ((broadcastCode.length > 16) || (broadcastCode.length < 4))) {
            Log.e(TAG, "Invalid broadcast code length. Should be from 4 to 16 octets long.");
            return BluetoothStatusCodes.ERROR_LE_BROADCAST_INVALID_CODE;
        }

        List<BluetoothLeBroadcastSubgroupSettings> settingsList =
                broadcastSettings.getSubgroupSettings();
        if (settingsList == null || settingsList.size() < 1) {
            Log.d(TAG, "subgroup settings is not valid value");
            return BluetoothStatusCodes.ERROR_BAD_PARAMETERS;
        }

        return BluetoothStatusCodes.SUCCESS;
    }

    /**
     * Creates LeAudio Broadcast instance with BluetoothLeBroadcastSettings.
     *
     * @param broadcastSettings broadcast settings for this broadcast source
     */
    public void createBroadcast(BluetoothLeBroadcastSettings broadcastSettings) {
        if (mLeAudioBroadcasterNativeInterface == null) {
            Log.w(TAG, "Native interface not available.");
            return;
        }

        int canBroadcastBeCreatedReturnCode = canBroadcastBeCreated(broadcastSettings);
        if (canBroadcastBeCreatedReturnCode != BluetoothStatusCodes.SUCCESS) {
            mHandler.post(() -> notifyBroadcastStartFailed(canBroadcastBeCreatedReturnCode));
            return;
        }

        if (mAwaitingBroadcastCreateResponse) {
            mCreateBroadcastQueue.add(broadcastSettings);
            Log.i(TAG, "Broadcast creation queued due to waiting for a previous request response.");
@@ -1192,21 +1212,6 @@ public class LeAudioService extends ProfileService {
            }
        }

        byte[] broadcastCode = broadcastSettings.getBroadcastCode();
        boolean isEncrypted = (broadcastCode != null) && (broadcastCode.length != 0);
        if (isEncrypted) {
            if ((broadcastCode.length > 16) || (broadcastCode.length < 4)) {
                Log.e(TAG, "Invalid broadcast code length. Should be from 4 to 16 octets long.");
                return;
            }
        }

        List<BluetoothLeBroadcastSubgroupSettings> settingsList =
                broadcastSettings.getSubgroupSettings();
        if (settingsList == null || settingsList.size() < 1) {
            Log.d(TAG, "subgroup settings is not valid value");
            return;
        }
        mBroadcastSessionStats.put(
                INVALID_BROADCAST_ID,
                new LeAudioBroadcastSessionStats(broadcastSettings, SystemClock.elapsedRealtime()));
@@ -1214,19 +1219,37 @@ public class LeAudioService extends ProfileService {
        BluetoothLeAudioContentMetadata publicMetadata =
                broadcastSettings.getPublicBroadcastMetadata();

        Log.i(TAG, "createBroadcast: isEncrypted=" + (isEncrypted ? "true" : "false"));
        byte[] broadcastCode = broadcastSettings.getBroadcastCode();
        Log.i(
                TAG,
                "createBroadcast: isEncrypted="
                        + (((broadcastCode != null) && (broadcastCode.length != 0))
                                ? "true"
                                : "false"));

        mAwaitingBroadcastCreateResponse = true;
        if (leaudioBigDependsOnAudioState()) {
            mCreateBroadcastQueue.add(broadcastSettings);
        }

        if (leaudioBigDependsOnAudioState()) {
            /* Start timeout to recover from stucked/error create Broadcast operation */
            if (mCreateBroadcastTimeoutEvent != null) {
                Log.w(TAG, "CreateBroadcastTimeoutEvent already scheduled");
            } else {
                mCreateBroadcastTimeoutEvent = new CreateBroadcastTimeoutEvent();
                mHandler.postDelayed(mCreateBroadcastTimeoutEvent, CREATE_BROADCAST_TIMEOUT_MS);
            }
        }

        mLeAudioBroadcasterNativeInterface.createBroadcast(
                broadcastSettings.isPublicBroadcast(),
                broadcastSettings.getBroadcastName(),
                broadcastCode,
                publicMetadata == null ? null : publicMetadata.getRawMetadata(),
                getBroadcastAudioQualityPerSinkCapabilities(settingsList),
                settingsList.stream()
                getBroadcastAudioQualityPerSinkCapabilities(
                        broadcastSettings.getSubgroupSettings()),
                broadcastSettings.getSubgroupSettings().stream()
                        .map(s -> s.getContentMetadata().getRawMetadata())
                        .toArray(byte[][]::new));
    }
@@ -1280,8 +1303,8 @@ public class LeAudioService extends ProfileService {
        Log.d(TAG, "startBroadcast");

        /* Start timeout to recover from stucked/error start Broadcast operation */
        mDialingOutTimeoutEvent = new DialingOutTimeoutEvent(broadcastId);
        mHandler.postDelayed(mDialingOutTimeoutEvent, DIALING_OUT_TIMEOUT_MS);
        mCreateBroadcastTimeoutEvent = new CreateBroadcastTimeoutEvent(broadcastId);
        mHandler.postDelayed(mCreateBroadcastTimeoutEvent, CREATE_BROADCAST_TIMEOUT_MS);

        mLeAudioBroadcasterNativeInterface.startBroadcast(broadcastId);
    }
@@ -3181,19 +3204,19 @@ public class LeAudioService extends ProfileService {
        setActiveDevice(unicastDevice);
    }

    void clearBroadcastTimeoutCallback() {
    private void clearCreateBroadcastTimeoutCallback() {
        if (mHandler == null) {
            Log.e(TAG, "No callback handler");
            return;
        }

        /* Timeout callback already cleared */
        if (mDialingOutTimeoutEvent == null) {
        if (mCreateBroadcastTimeoutEvent == null) {
            return;
        }

        mHandler.removeCallbacks(mDialingOutTimeoutEvent);
        mDialingOutTimeoutEvent = null;
        mHandler.removeCallbacks(mCreateBroadcastTimeoutEvent);
        mCreateBroadcastTimeoutEvent = null;
    }

    void notifyAudioFrameworkForCodecConfigUpdate(
@@ -3669,7 +3692,10 @@ public class LeAudioService extends ProfileService {
                                if (!leaudioUseAudioModeListener()) {
                                    mQueuedInCallValue = Optional.empty();
                                }
                                startBroadcast(mBroadcastIdDeactivatedForUnicastTransition.get());
                                if (!leaudioBigDependsOnAudioState()) {
                                    startBroadcast(
                                            mBroadcastIdDeactivatedForUnicastTransition.get());
                                }
                                mBroadcastIdDeactivatedForUnicastTransition = Optional.empty();
                            }

@@ -3729,9 +3755,10 @@ public class LeAudioService extends ProfileService {
                    mBroadcastSessionStats.put(broadcastId, sessionStats);
                }

                if (!leaudioBigDependsOnAudioState()) {
                    // Start sending the actual stream
                    startBroadcast(broadcastId);

                }
            } else {
                // TODO: Improve reason reporting or extend the native stack event with reason code
                Log.e(
@@ -3744,7 +3771,9 @@ public class LeAudioService extends ProfileService {
                if ((mUnicastGroupIdDeactivatedForBroadcastTransition != LE_AUDIO_GROUP_ID_INVALID)
                        && mCreateBroadcastQueue.isEmpty()
                        && (!Objects.equals(device, mActiveBroadcastAudioDevice))) {
                    clearBroadcastTimeoutCallback();
                    if (!leaudioBigDependsOnAudioState()) {
                        clearCreateBroadcastTimeoutCallback();
                    }
                    updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                }

@@ -3755,6 +3784,9 @@ public class LeAudioService extends ProfileService {
                                .BROADCAST_AUDIO_SESSION_REPORTED__SESSION_SETUP_STATUS__SETUP_STATUS_CREATE_FAILED);
            }

            if (leaudioBigDependsOnAudioState()) {
                clearCreateBroadcastTimeoutCallback();
            }
            mAwaitingBroadcastCreateResponse = false;

            // In case if there were additional calls to create broadcast
@@ -3883,7 +3915,9 @@ public class LeAudioService extends ProfileService {
                        sessionStats.updateSessionStreamingTime(SystemClock.elapsedRealtime());
                    }

                    clearBroadcastTimeoutCallback();
                    if (!leaudioBigDependsOnAudioState()) {
                        clearCreateBroadcastTimeoutCallback();
                    }

                    if (previousState == LeAudioStackEvent.BROADCAST_STATE_PAUSED) {
                        if (bassClientService != null) {
@@ -5279,21 +5313,38 @@ public class LeAudioService extends ProfileService {
        return audioFrameworkCalls;
    }

    class DialingOutTimeoutEvent implements Runnable {
    private class CreateBroadcastTimeoutEvent implements Runnable {
        Integer mBroadcastId;

        DialingOutTimeoutEvent(Integer broadcastId) {
        CreateBroadcastTimeoutEvent() {}

        CreateBroadcastTimeoutEvent(Integer broadcastId) {
            mBroadcastId = broadcastId;
        }

        @Override
        public void run() {
            if (leaudioBigDependsOnAudioState()) {
                Log.w(TAG, "Failed to start Broadcast in time");

                if (getLeAudioService() == null) {
                    Log.e(TAG, "CreateBroadcastTimeoutEvent: No LE Audio service");
                    return;
                }

                if (sLeAudioService.mHandler == null) {
                    Log.w(TAG, "CreateBroadcastTimeoutEvent: No handler");
                    return;
                }

                mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT));
            } else {
                Log.w(TAG, "Failed to start Broadcast in time: " + mBroadcastId);

            mDialingOutTimeoutEvent = null;
                mCreateBroadcastTimeoutEvent = null;

                if (getLeAudioService() == null) {
                Log.e(TAG, "DialingOutTimeoutEvent: No LE Audio service");
                    Log.e(TAG, "CreateBroadcastTimeoutEvent: No LE Audio service");
                    return;
                }

@@ -5313,7 +5364,8 @@ public class LeAudioService extends ProfileService {
                        updateBroadcastActiveDevice(null, mActiveBroadcastAudioDevice, false);
                    }

                mHandler.post(() -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT));
                    mHandler.post(
                            () -> notifyBroadcastStartFailed(BluetoothStatusCodes.ERROR_TIMEOUT));
                    logBroadcastSessionStatsWithStatus(
                            mBroadcastId,
                            BluetoothStatsLog
@@ -5321,6 +5373,7 @@ public class LeAudioService extends ProfileService {
                }
            }
        }
    }

    class AudioModeChangeListener implements AudioManager.OnModeChangedListener {
        @Override
+164 −140

File changed.

Preview size limit exceeded, changes collapsed.

+8 −5
Original line number Diff line number Diff line
@@ -913,6 +913,7 @@ public:
    is_iso_running_ = is_active;
    log::info("is_iso_running: {}", is_iso_running_);
    if (!is_iso_running_) {
      if (!com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) {
        if (queued_start_broadcast_request_) {
          auto broadcast_id = *queued_start_broadcast_request_;
          queued_start_broadcast_request_ = std::nullopt;
@@ -920,6 +921,8 @@ public:
          log::info("Start queued broadcast.");
          StartAudioBroadcast(broadcast_id);
        }
      }

      if (queued_create_broadcast_request_) {
        auto broadcast_msg = std::move(*queued_create_broadcast_request_);
        queued_create_broadcast_request_ = std::nullopt;
+36 −63
Original line number Diff line number Diff line
@@ -533,8 +533,19 @@ TEST_F(BroadcasterTest, CreateAudioBroadcastMultiGroups) {
TEST_F(BroadcasterTest, SuspendAudioBroadcast) {
  EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
          .Times(1);
  LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
  EXPECT_CALL(*mock_audio_source_, Start)
          .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)))
          .WillRepeatedly(Return(false));
  auto broadcast_id = InstantiateBroadcast();

  if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) {
    ASSERT_NE(audio_receiver, nullptr);
    audio_receiver->OnAudioResume();
  } else {
    LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  }

  Mock::VerifyAndClearExpectations(mock_codec_manager_);

  EXPECT_CALL(mock_broadcaster_callbacks_,
@@ -559,7 +570,9 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) {

  EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
          .Times(1);

  auto broadcast_id = InstantiateBroadcast();
  ASSERT_NE(audio_receiver, nullptr);
  Mock::VerifyAndClearExpectations(mock_codec_manager_);

  EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
@@ -575,8 +588,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcast) {
  ASSERT_TRUE(big_terminate_timer_->cb == nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  ASSERT_NE(audio_receiver, nullptr);
  audio_receiver->OnAudioResume();

  // NOTICE: This is really an implementation specific part, we fake the BIG
  //         config as the mocked state machine does not even call the
@@ -609,6 +621,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
          .Times(1);
  auto broadcast_id =
          InstantiateBroadcast(media_metadata, default_code, {bluetooth::le_audio::QUALITY_HIGH});
  ASSERT_NE(audio_receiver, nullptr);
  Mock::VerifyAndClearExpectations(mock_codec_manager_);

  LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);
@@ -626,8 +639,7 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
  EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, false))
          .Times(0);

  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  ASSERT_NE(audio_receiver, nullptr);
  audio_receiver->OnAudioResume();

  // NOTICE: This is really an implementation specific part, we fake the BIG
  //         config as the mocked state machine does not even call the
@@ -651,8 +663,18 @@ TEST_F(BroadcasterTest, StartAudioBroadcastMedia) {
TEST_F(BroadcasterTest, StopAudioBroadcast) {
  EXPECT_CALL(*mock_codec_manager_, UpdateActiveBroadcastAudioHalClient(mock_audio_source_, true))
          .Times(1);
  LeAudioSourceAudioHalClient::Callbacks* audio_receiver;
  EXPECT_CALL(*mock_audio_source_, Start)
          .WillOnce(DoAll(SaveArg<1>(&audio_receiver), Return(true)))
          .WillRepeatedly(Return(false));
  auto broadcast_id = InstantiateBroadcast();

  if (com::android::bluetooth::flags::leaudio_big_depends_on_audio_state()) {
    ASSERT_NE(audio_receiver, nullptr);
    audio_receiver->OnAudioResume();
  } else {
    LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  }

  // NOTICE: This is really an implementation specific part, we fake the BIG
  //         config as the mocked state machine does not even call the
@@ -712,7 +734,6 @@ TEST_F(BroadcasterTest, DestroyAudioBroadcast) {
  LeAudioBroadcaster::Get()->StopAudioBroadcast(broadcast_id);

  EXPECT_CALL(*mock_audio_source_, Start).Times(0);
  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);

  EXPECT_CALL(*mock_audio_source_, Stop).Times(0);
  LeAudioBroadcaster::Get()->SuspendAudioBroadcast(broadcast_id);
@@ -846,8 +867,8 @@ TEST_F(BroadcasterTest, UpdateMetadataFromAudioTrackMetadata) {
  ContentControlIdKeeper::GetInstance()->SetCcid(LeAudioContextType::MEDIA, media_ccid);
  auto broadcast_id = InstantiateBroadcast();

  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  ASSERT_NE(audio_receiver, nullptr);
  audio_receiver->OnAudioResume();

  auto sm = MockBroadcastStateMachine::GetLastInstance();
  std::vector<uint8_t> ccid_list;
@@ -1204,6 +1225,7 @@ TEST_F(BroadcasterTest, AudioActiveState) {
          .WillRepeatedly(Return(false));

  auto broadcast_id = InstantiateBroadcast();
  ASSERT_NE(audio_receiver, nullptr);
  auto sm = MockBroadcastStateMachine::GetLastInstance();
  pb_announcement = sm->GetPublicBroadcastAnnouncement();
  auto created_public_meta = types::LeAudioLtvMap(pb_announcement.metadata).RawPacket();
@@ -1218,9 +1240,6 @@ TEST_F(BroadcasterTest, AudioActiveState) {
                  });
  ON_CALL(*sm, GetPublicBroadcastAnnouncement()).WillByDefault(ReturnRef(pb_announcement));

  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  ASSERT_NE(audio_receiver, nullptr);

  // Update to true Audio Active State while audio resumed
  EXPECT_CALL(*sm, UpdatePublicBroadcastAnnouncement);
  audio_receiver->OnAudioResume();
@@ -1278,32 +1297,12 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundFromTheBeginnin
  auto broadcast_id = InstantiateBroadcast();
  EXPECT_CALL(mock_broadcaster_callbacks_,
              OnBroadcastStateChanged(broadcast_id, BroadcastState::STREAMING))
          .Times(1);
          .Times(0);
  // Timers not started
  ASSERT_TRUE(big_terminate_timer_->cb == nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  // Start Broadcast
  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  // Timers started
  ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);
  ASSERT_EQ(0, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_NE(audio_receiver, nullptr);

  // BIG termination timer execution, state machine go to CONFIGURED state so BIG terminated
  EXPECT_CALL(mock_broadcaster_callbacks_,
              OnBroadcastStateChanged(broadcast_id, BroadcastState::CONFIGURED))
          .Times(1);
  // Imitate execution of BIG termination timer
  big_terminate_timer_->cb(big_terminate_timer_->data);

  // Broadcast stop timer execution, state machine go to STOPPED state
  EXPECT_CALL(mock_broadcaster_callbacks_,
              OnBroadcastStateChanged(broadcast_id, BroadcastState::STOPPED))
          .Times(1);
  // Imitate execution of BIG termination timer
  broadcast_stop_timer_->cb(broadcast_stop_timer_->data);
}

TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) {
@@ -1326,24 +1325,11 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) {
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  // Start Broadcast
  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  // Timers started
  ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);
  ASSERT_NE(audio_receiver, nullptr);

  // First onAudioResume when BIG already created, not cause any state change
  EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, _)).Times(0);
  audio_receiver->OnAudioResume();
  // Timers cancelled
  ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
  ASSERT_TRUE(big_terminate_timer_->cb == nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  // OnAudioSuspend cause starting the BIG termination timer
  audio_receiver->OnAudioSuspend();
  ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);

@@ -1357,7 +1343,7 @@ TEST_F(BroadcasterTest, BigTerminationAndBroadcastStopWhenNoSoundAfterSuspend) {

  // OnAudioSuspend cause starting the BIG termination timer
  audio_receiver->OnAudioSuspend();
  ASSERT_EQ(6, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);

@@ -1396,24 +1382,11 @@ TEST_F(BroadcasterTest, BigCreationTerminationDependsOnAudioResumeSuspend) {
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  // Start Broadcast
  LeAudioBroadcaster::Get()->StartAudioBroadcast(broadcast_id);
  // Timers started
  ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);
  ASSERT_NE(audio_receiver, nullptr);

  // First onAudioResume when BIG already created, not cause any state change
  EXPECT_CALL(mock_broadcaster_callbacks_, OnBroadcastStateChanged(broadcast_id, _)).Times(0);
  audio_receiver->OnAudioResume();
  // Timers cancelled
  ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
  ASSERT_TRUE(big_terminate_timer_->cb == nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb == nullptr);

  // OnAudioSuspend cause starting the BIG termination timer
  audio_receiver->OnAudioSuspend();
  ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(2, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);

@@ -1427,7 +1400,7 @@ TEST_F(BroadcasterTest, BigCreationTerminationDependsOnAudioResumeSuspend) {

  // OnAudioSuspend cause starting the BIG termination timer
  audio_receiver->OnAudioSuspend();
  ASSERT_EQ(6, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_EQ(4, get_func_call_count("alarm_set_on_mloop"));
  ASSERT_TRUE(big_terminate_timer_->cb != nullptr);
  ASSERT_TRUE(broadcast_stop_timer_->cb != nullptr);

+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ public:
    advertising_sid_ = ++instance_counter_;

    ON_CALL(*this, Initialize).WillByDefault([this]() {
      SetState(State::CONFIGURED);
      this->cb->OnStateMachineCreateStatus(this->cfg.broadcast_id, result_);
      return result_;
    });