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

Commit fcda2cdf authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge changes I53615d19,I7e7e6784 am: e738297a

parents b963d4bf e738297a
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -146,9 +146,12 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
     * Limitation here is that device should be previously in the streaming
     * group and just got reconnected.
     */
    if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
      LOG_ERROR(" group not in the streaming state: %s",
                ToString(group->GetState()).c_str());
    if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING ||
        group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
      LOG_ERROR(
          " group %d no in correct streaming state: %s or target state: %s",
          group->group_id_, ToString(group->GetState()).c_str(),
          ToString(group->GetTargetState()).c_str());
      return false;
    }

+168 −0
Original line number Diff line number Diff line
@@ -3353,6 +3353,174 @@ TEST_F(StateMachineTest, testAttachDeviceToTheStream) {
  ASSERT_NE(ase->retrans_nb, 0);
}

TEST_F(StateMachineTest, testAttachDeviceToTheStreamDoNotAttach) {
  const auto context_type = kContextTypeMedia;
  const auto leaudio_group_id = 6;
  const auto num_devices = 2;

  ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);

  // Prepare multiple fake connected devices in a group
  auto* group =
      PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);

  auto* leAudioDevice = group->GetFirstDevice();
  LeAudioDevice* lastDevice;

  while (leAudioDevice) {
    lastDevice = leAudioDevice;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }

  InjectInitialIdleNotification(group);

  // Inject CIS and ACL disconnection of first device
  InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
  InjectAclDisconnected(group, lastDevice);

  // Start the configuration and stream Media content
  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
  LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)});

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);

  // Check if group keeps streaming
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

  lastDevice->conn_id_ = 3;
  lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);

  group->UpdateAudioContextTypeAvailability();

  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::RELEASING));
  LeAudioGroupStateMachine::Get()->StopStream(group);
  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);

  ASSERT_FALSE(
      LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice));
}

TEST_F(StateMachineTest, testReconfigureAfterLateDeviceAttached) {
  const auto context_type = kContextTypeMedia;
  const auto leaudio_group_id = 6;
  const auto num_devices = 2;

  ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);

  // Prepare multiple fake connected devices in a group
  auto* group =
      PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group, 0, true);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);
  PrepareDisableHandler(group);
  PrepareReleaseHandler(group);

  auto* leAudioDevice = group->GetFirstDevice();
  LeAudioDevice* lastDevice;
  LeAudioDevice* fistDevice = leAudioDevice;

  while (leAudioDevice) {
    lastDevice = leAudioDevice;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }

  InjectInitialIdleNotification(group);

  // Inject CIS and ACL disconnection of first device
  InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
  InjectAclDisconnected(group, lastDevice);

  /* First device connected. Configure it to stream media */

  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);

  types::BidirectionalPair<std::vector<uint8_t>> ccids_list = {
      .sink = {media_ccid}, .source = {media_ccid}};

  // Start the configuration and stream Media content
  LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)},
      ccids_list);

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);

  /* Stop  the stream and let first device to stay in configured state (caching
   * is on)*/
  LeAudioGroupStateMachine::Get()->StopStream(group);
  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);

  /* Verify state in the configured state */
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);

  /* Now when stream is stopped, connect second device. */
  lastDevice->conn_id_ = 3;
  lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);

  group->UpdateAudioContextTypeAvailability();

  /* Start stream, make sure 2 devices are started. */

  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);

  // Start the configuration and stream Media content
  LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)},
      ccids_list);

  // Check if group keeps streaming
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

  // Verify that both devicse receives the right CCID list and both are
  // streaming
  auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
  bool parsedOk = false;
  auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(),
                                                   lastMeta.size(), parsedOk);
  ASSERT_TRUE(parsedOk);

  auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
  ASSERT_TRUE(ccids.has_value());
  ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());

  /* Verify that ASE of first device are still good*/
  auto ase = fistDevice->GetFirstActiveAse();
  ASSERT_NE(ase->max_transport_latency, 0);
  ASSERT_NE(ase->retrans_nb, 0);
}

TEST_F(StateMachineTest, testStreamToGettingReadyDevice) {
  const auto context_type = kContextTypeLive;
  const auto leaudio_group_id = 666;