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

Commit 8bdea4b1 authored by Ajay Panicker's avatar Ajay Panicker
Browse files

Disable absolute volume if the remote device rejects registration

Instead of trying to re-register for a rejected volume changed
notification, disable absolute volume. This prevents spinning if a
remote device continuously rejects all attempts to register. A volume
level of -2 will be used to represent that the volume notification was
rejected.

Bug: 77238060
Test: Run host native test net_test_avrcp
Change-Id: I228524fb30348ca691d0792f0c7bcc4653d1fcef
parent 70958dd0
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -134,6 +134,10 @@ std::vector<uint8_t> interim_uids_notificaiton = {0x0f, 0x48, 0x00, 0x00, 0x19,
std::vector<uint8_t> interim_volume_changed_notification = {
    0x0f, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x47};

// AVRCP Rejected Volume Changed Notification with volume at 0%
std::vector<uint8_t> rejected_volume_changed_notification = {
    0x0a, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x00};

// AVRCP Changed Volume Changed Notification with volume at 55% (0x47)
std::vector<uint8_t> changed_volume_changed_notification = {
    0x0d, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x02, 0x0d, 0x47};
+22 −3
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ namespace avrcp {
#define DEVICE_LOG(LEVEL) LOG(LEVEL) << address_.ToString() << " : "
#define DEVICE_VLOG(LEVEL) VLOG(LEVEL) << address_.ToString() << " : "

#define VOL_NOT_SUPPORTED -1
#define VOL_REGISTRATION_FAILED -2

Device::Device(
    const RawAddress& bdaddr, bool avrcp13_compatibility,
    base::Callback<void(uint8_t label, bool browse,
@@ -253,6 +256,14 @@ void Device::HandleVolumeChanged(
  DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
  if (volume_interface_ == nullptr) return;

  if (pkt->GetCType() == CType::REJECTED) {
    // Disable Absolute Volume
    active_labels_.erase(label);
    volume_interface_ = nullptr;
    volume_ = VOL_REGISTRATION_FAILED;
    return;
  }

  // We only update on interim and just re-register on changes.
  if (!pkt->IsInterim()) {
    active_labels_.erase(label);
@@ -261,7 +272,7 @@ void Device::HandleVolumeChanged(
  }

  // Handle the first volume update.
  if (volume_ == -1) {
  if (volume_ == VOL_NOT_SUPPORTED) {
    volume_ = pkt->GetVolume();
    volume_interface_->DeviceConnected(
        GetAddress(), base::Bind(&Device::SetVolume, base::Unretained(this)));
@@ -290,6 +301,7 @@ void Device::SetVolume(int8_t volume) {
    }
  }

  volume_ = volume;
  send_message_cb_.Run(label, false, std::move(request));
}

@@ -1055,6 +1067,13 @@ void Device::DeviceDisconnected() {
    volume_interface_->DeviceDisconnected(GetAddress());
}

static std::string volumeToStr(int8_t volume) {
  if (volume == VOL_NOT_SUPPORTED) return "Absolute Volume not supported";
  if (volume == VOL_REGISTRATION_FAILED)
    return "Volume changed notification was rejected";
  return std::to_string(volume);
}

std::ostream& operator<<(std::ostream& out, const Device& d) {
  out << "Avrcp Device: Address=" << d.address_.ToString() << std::endl;
  out << "  └ isActive: " << (d.IsActive() ? "YES" : "NO") << std::endl;
@@ -1072,7 +1091,7 @@ std::ostream& operator<<(std::ostream& out, const Device& d) {
  out << "    └ UIDs Changed: " << d.uids_changed_.first << std::endl;
  out << "  └ Last Song Sent ID: " << d.last_song_info_.media_id << std::endl;
  out << "  └ Last Play State: " << d.last_play_status_.state << std::endl;
  out << "  └ Current Volume: " << d.volume_ << std::endl;
  out << "  └ Current Volume: " << volumeToStr(d.volume_) << std::endl;
  out << "  └ Current Folder: " << d.CurrentFolder();
  out << "  └ Control MTU Size: " << d.ctrl_mtu_ << std::endl;
  out << "  └ Browse MTU Size: " << d.browse_mtu_ << std::endl;
+19 −0
Original line number Diff line number Diff line
@@ -678,5 +678,24 @@ TEST_F(AvrcpDeviceTest, volumeChangedTest) {
  SendMessage(1, response);
}

TEST_F(AvrcpDeviceTest, volumeRejectedTest) {
  MockMediaInterface interface;
  NiceMock<MockA2dpInterface> a2dp_interface;
  MockVolumeInterface vol_interface;

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

  auto reg_notif =
      RegisterNotificationRequestBuilder::MakeBuilder(Event::VOLUME_CHANGED, 0);
  EXPECT_CALL(response_cb, Call(_, false, matchPacket(std::move(reg_notif))))
      .Times(1);
  test_device->RegisterVolumeChanged();

  auto response = TestAvrcpPacket::Make(rejected_volume_changed_notification);
  SendMessage(1, response);

  EXPECT_CALL(response_cb, Call(_, _, _)).Times(0);
}

}  // namespace avrcp
}  // namespace bluetooth
 No newline at end of file