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

Commit a22a30a0 authored by Jakub Rotkiewicz's avatar Jakub Rotkiewicz Committed by Gerrit Code Review
Browse files

Merge "avrcp/device: Fix nullptr dereference on floss"

parents 51095246 dee16ce2
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
@@ -214,12 +214,29 @@ void Device::VendorPacketHandler(uint8_t label,
    } break;

    case CommandPdu::LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES: {
      if (player_settings_interface_ == nullptr) {
        LOG(ERROR) << __func__
                   << ": Player Settings Interface not initialized.";
        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                   Status::INVALID_COMMAND);
        send_message(label, false, std::move(response));
        return;
      }

      player_settings_interface_->ListPlayerSettings(
          base::Bind(&Device::ListPlayerApplicationSettingAttributesResponse,
                     weak_ptr_factory_.GetWeakPtr(), label));
    } break;

    case CommandPdu::LIST_PLAYER_APPLICATION_SETTING_VALUES: {
      if (player_settings_interface_ == nullptr) {
        LOG(ERROR) << __func__
                   << ": Player Settings Interface not initialized.";
        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                   Status::INVALID_COMMAND);
        send_message(label, false, std::move(response));
        return;
      }
      auto list_player_setting_values_request =
          Packet::Specialize<ListPlayerApplicationSettingValuesRequest>(pkt);

@@ -250,6 +267,14 @@ void Device::VendorPacketHandler(uint8_t label,
    } break;

    case CommandPdu::GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE: {
      if (player_settings_interface_ == nullptr) {
        LOG(ERROR) << __func__
                   << ": Player Settings Interface not initialized.";
        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                   Status::INVALID_COMMAND);
        send_message(label, false, std::move(response));
        return;
      }
      auto get_current_player_setting_value_request =
          Packet::Specialize<GetCurrentPlayerApplicationSettingValueRequest>(
              pkt);
@@ -283,6 +308,14 @@ void Device::VendorPacketHandler(uint8_t label,
    } break;

    case CommandPdu::SET_PLAYER_APPLICATION_SETTING_VALUE: {
      if (player_settings_interface_ == nullptr) {
        LOG(ERROR) << __func__
                   << ": Player Settings Interface not initialized.";
        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                   Status::INVALID_COMMAND);
        send_message(label, false, std::move(response));
        return;
      }
      auto set_player_setting_value_request =
          Packet::Specialize<SetPlayerApplicationSettingValueRequest>(pkt);

@@ -379,7 +412,9 @@ void Device::HandleGetCapabilities(
              Event::PLAYBACK_STATUS_CHANGED);
      response->AddEvent(Event::TRACK_CHANGED);
      response->AddEvent(Event::PLAYBACK_POS_CHANGED);
      if (player_settings_interface_ != nullptr) {
        response->AddEvent(Event::PLAYER_APPLICATION_SETTING_CHANGED);
      }

      if (!avrcp13_compatibility_) {
        response->AddEvent(Event::AVAILABLE_PLAYERS_CHANGED);
@@ -434,6 +469,14 @@ void Device::HandleNotification(
    } break;

    case Event::PLAYER_APPLICATION_SETTING_CHANGED: {
      if (player_settings_interface_ == nullptr) {
        LOG(ERROR) << __func__
                   << ": Player Settings Interface not initialized.";
        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                   Status::INVALID_COMMAND);
        send_message(label, false, std::move(response));
        return;
      }
      std::vector<PlayerAttribute> attributes = {
          PlayerAttribute::EQUALIZER, PlayerAttribute::REPEAT,
          PlayerAttribute::SHUFFLE, PlayerAttribute::SCAN};
@@ -1683,7 +1726,7 @@ void Device::HandlePlayerSettingChanged(std::vector<PlayerAttribute> attributes,
  auto response =
      RegisterNotificationResponseBuilder::MakePlayerSettingChangedBuilder(
          false, attributes, values);
  send_message(now_playing_changed_.second, false, std::move(response));
  send_message(player_setting_changed_.second, false, std::move(response));
}

void Device::PlayerSettingChangedNotificationResponse(
@@ -1712,11 +1755,11 @@ void Device::PlayerSettingChangedNotificationResponse(
  auto response =
      RegisterNotificationResponseBuilder::MakePlayerSettingChangedBuilder(
          interim, attributes, values);
  send_message(now_playing_changed_.second, false, std::move(response));
  send_message(player_setting_changed_.second, false, std::move(response));

  if (!interim) {
    active_labels_.erase(label);
    now_playing_changed_ = Notification(false, 0);
    player_setting_changed_ = Notification(false, 0);
  }
}

+189 −1
Original line number Diff line number Diff line
@@ -175,6 +175,67 @@ TEST_F(AvrcpDeviceTest, trackChangedTest) {
  test_device->HandleTrackUpdate();
}

TEST_F(AvrcpDeviceTest, playerSettingsChangedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
  MockPlayerSettingsInterface player_settings_interface;
  std::vector<PlayerAttribute> attributes = {PlayerAttribute::REPEAT,
                                             PlayerAttribute::SHUFFLE};
  std::vector<uint8_t> attributes_values = {
      static_cast<uint8_t>(PlayerRepeatValue::OFF),
      static_cast<uint8_t>(PlayerShuffleValue::ALL)};

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  &player_settings_interface);

  EXPECT_CALL(player_settings_interface, GetCurrentPlayerSettingValue(_, _))
      .Times(1)
      .WillRepeatedly(InvokeCb<1>(attributes, attributes_values));

  // Test the interim response for player settings changed
  auto interim_response =
      RegisterNotificationResponseBuilder::MakePlayerSettingChangedBuilder(
          true, attributes, attributes_values);
  EXPECT_CALL(response_cb,
              Call(1, false, matchPacket(std::move(interim_response))))
      .Times(1);

  auto request = RegisterNotificationRequestBuilder::MakeBuilder(
      Event::PLAYER_APPLICATION_SETTING_CHANGED, 0);
  auto pkt = TestAvrcpPacket::Make();
  request->Serialize(pkt);
  SendMessage(1, pkt);

  // Test the changed response for player settings changed
  auto changed_response =
      RegisterNotificationResponseBuilder::MakePlayerSettingChangedBuilder(
          false, attributes, attributes_values);
  EXPECT_CALL(response_cb,
              Call(1, false, matchPacket(std::move(changed_response))))
      .Times(1);

  test_device->HandlePlayerSettingChanged(attributes, attributes_values);
}

TEST_F(AvrcpDeviceTest, playerSettingsChangedNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  auto response = RejectBuilder::MakeBuilder(CommandPdu::REGISTER_NOTIFICATION,
                                             Status::INVALID_COMMAND);
  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(response))))
      .Times(1);

  auto request = RegisterNotificationRequestBuilder::MakeBuilder(
      Event::PLAYER_APPLICATION_SETTING_CHANGED, 0);
  auto pkt = TestAvrcpPacket::Make();
  request->Serialize(pkt);
  SendMessage(1, pkt);
}

TEST_F(AvrcpDeviceTest, playStatusTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
@@ -1532,9 +1593,10 @@ TEST_F(AvrcpDeviceTest, mediaKeyInactiveDeviceTest) {
TEST_F(AvrcpDeviceTest, getCapabilitiesTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
  MockPlayerSettingsInterface player_settings_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);
                                  &player_settings_interface);

  // GetCapabilities with CapabilityID COMPANY_ID
  auto request_company_id_response =
@@ -1580,6 +1642,55 @@ TEST_F(AvrcpDeviceTest, getCapabilitiesTest) {
  SendMessage(3, request_unknown);
}

TEST_F(AvrcpDeviceTest, getCapabilitiesPlayerSettingsNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  // GetCapabilities with CapabilityID COMPANY_ID
  auto request_company_id_response =
      GetCapabilitiesResponseBuilder::MakeCompanyIdBuilder(0x001958);
  request_company_id_response->AddCompanyId(0x002345);
  EXPECT_CALL(
      response_cb,
      Call(1, false, matchPacket(std::move(request_company_id_response))))
      .Times(1);

  auto request_company_id =
      TestAvrcpPacket::Make(get_capabilities_request_company_id);
  SendMessage(1, request_company_id);

  // GetCapabilities with CapabilityID EVENTS_SUPPORTED
  auto request_events_supported_response =
      GetCapabilitiesResponseBuilder::MakeEventsSupportedBuilder(
          Event::PLAYBACK_STATUS_CHANGED);
  request_events_supported_response->AddEvent(Event::TRACK_CHANGED);
  request_events_supported_response->AddEvent(Event::PLAYBACK_POS_CHANGED);

  EXPECT_CALL(
      response_cb,
      Call(2, false, matchPacket(std::move(request_events_supported_response))))
      .Times(1);

  auto request_events_supported =
      TestAvrcpPacket::Make(get_capabilities_request);
  SendMessage(2, request_events_supported);

  // GetCapabilities with CapabilityID UNKNOWN
  auto request_unknown_response = RejectBuilder::MakeBuilder(
      CommandPdu::GET_CAPABILITIES, Status::INVALID_PARAMETER);

  EXPECT_CALL(response_cb,
              Call(3, false, matchPacket(std::move(request_unknown_response))))
      .Times(1);

  auto request_unknown =
      TestAvrcpPacket::Make(get_capabilities_request_unknown);
  SendMessage(3, request_unknown);
}

TEST_F(AvrcpDeviceTest, getInvalidItemAttributesTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
@@ -1647,6 +1758,25 @@ TEST_F(AvrcpDeviceTest, listPlayerSettingsTest) {
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, listPlayerSettingsNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  auto response = RejectBuilder::MakeBuilder(
      CommandPdu::LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES,
      Status::INVALID_COMMAND);

  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(response))))
      .Times(1);

  auto request =
      TestAvrcpPacket::Make(list_player_application_setting_attributes_request);
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, listPlayerSettingValuesTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
@@ -1679,6 +1809,25 @@ TEST_F(AvrcpDeviceTest, listPlayerSettingValuesTest) {
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, listPlayerSettingValuesNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  auto response = RejectBuilder::MakeBuilder(
      CommandPdu::LIST_PLAYER_APPLICATION_SETTING_VALUES,
      Status::INVALID_COMMAND);

  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(response))))
      .Times(1);

  auto request = TestAvrcpPacket::Make(
      list_player_application_setting_attribute_values_request);
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, invalidSettingListPlayerSettingValuesTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
@@ -1749,6 +1898,26 @@ TEST_F(AvrcpDeviceTest, getCurrentPlayerApplicationSettingValueTest) {
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest,
       getCurrentPlayerApplicationSettingValueNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  auto response = RejectBuilder::MakeBuilder(
      CommandPdu::GET_CURRENT_PLAYER_APPLICATION_SETTING_VALUE,
      Status::INVALID_COMMAND);

  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(response))))
      .Times(1);

  auto request = TestAvrcpPacket::Make(
      get_current_player_application_setting_value_request);
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest,
       invalidSettingGetCurrentPlayerApplicationSettingValueTest) {
  MockMediaInterface interface;
@@ -1819,6 +1988,25 @@ TEST_F(AvrcpDeviceTest, setPlayerApplicationSettingValueTest) {
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, setPlayerApplicationSettingValueNotSupportedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;

  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr,
                                  nullptr);

  auto response = RejectBuilder::MakeBuilder(
      CommandPdu::SET_PLAYER_APPLICATION_SETTING_VALUE,
      Status::INVALID_COMMAND);

  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(response))))
      .Times(1);

  auto request =
      TestAvrcpPacket::Make(set_player_application_setting_value_request);
  SendMessage(1, request);
}

TEST_F(AvrcpDeviceTest, invalidSettingSetPlayerApplicationSettingValueTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;