Loading system/packet/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_test { "tests/avrcp/pass_through_packet_test.cc", "tests/avrcp/play_item_packet_test.cc", "tests/avrcp/register_notification_packet_test.cc", "tests/avrcp/set_absolute_volume_packet_test.cc", "tests/avrcp/set_browsed_player_packet_test.cc", "tests/avrcp/vendor_packet_test.cc", "tests/base/iterator_test.cc", Loading system/packet/avrcp/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ cc_library_static { "pass_through_packet.cc", "play_item.cc", "register_notification_packet.cc", "set_absolute_volume.cc", "set_browsed_player.cc", "vendor_packet.cc", ], Loading system/packet/avrcp/avrcp_common.h +1 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ enum class CommandPdu : uint8_t { GET_ELEMENT_ATTRIBUTES = 0x20, GET_PLAY_STATUS = 0x30, REGISTER_NOTIFICATION = 0x31, SET_ABSOLUTE_VOLUME = 0x50, SET_ADDRESSED_PLAYER = 0x60, PLAY_ITEM = 0x74, }; Loading system/packet/avrcp/register_notification_packet.cc +113 −16 Original line number Diff line number Diff line Loading @@ -21,6 +21,54 @@ namespace bluetooth { namespace avrcp { bool RegisterNotificationResponse::IsInterim() const { return GetCType() == CType::INTERIM; } Event RegisterNotificationResponse::GetEvent() const { auto value = *(begin() + VendorPacket::kMinSize()); return static_cast<Event>(value); } uint8_t RegisterNotificationResponse::GetVolume() const { CHECK(GetEvent() == Event::VOLUME_CHANGED); auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1); return *it; } bool RegisterNotificationResponse::IsValid() const { if (!VendorPacket::IsValid()) return false; if (size() < kMinSize()) return false; if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED) return false; switch (GetEvent()) { case Event::VOLUME_CHANGED: return size() == (kMinSize() + 1); default: // TODO (apanicke): Add the remaining events when implementing AVRCP // Controller return false; } } std::string RegisterNotificationResponse::ToString() const { std::stringstream ss; ss << "RegisterNotificationResponse: " << std::endl; ss << " └ cType = " << GetCType() << std::endl; ss << " └ Subunit Type = " << loghex(GetSubunitType()) << std::endl; ss << " └ Subunit ID = " << loghex(GetSubunitId()) << std::endl; ss << " └ OpCode = " << GetOpcode() << std::endl; ss << " └ Company ID = " << loghex(GetCompanyId()) << std::endl; ss << " └ Command PDU = " << GetCommandPdu() << std::endl; ss << " └ PacketType = " << GetPacketType() << std::endl; ss << " └ Parameter Length = " << loghex(GetParameterLength()) << std::endl; ss << " └ Event Registered = " << GetEvent() << std::endl; ss << std::endl; return ss.str(); } std::unique_ptr<RegisterNotificationResponseBuilder> RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder( bool interim, uint8_t play_status) { Loading Loading @@ -124,22 +172,43 @@ bool RegisterNotificationResponseBuilder::Serialize( VendorPacketBuilder::PushHeader(pkt, 1 + data_size); AddPayloadOctets1(pkt, static_cast<uint8_t>(event_)); if (event_ == Event::PLAYBACK_STATUS_CHANGED) { switch (event_) { case Event::PLAYBACK_STATUS_CHANGED: { uint8_t playback_status = data_ & 0xFF; AddPayloadOctets1(pkt, playback_status); } else if (event_ == Event::TRACK_CHANGED) { break; } case Event::TRACK_CHANGED: { AddPayloadOctets8(pkt, base::ByteSwap(data_)); } else if (event_ == Event::PLAYBACK_POS_CHANGED) { break; } case Event::PLAYBACK_POS_CHANGED: { uint32_t playback_pos = data_ & 0xFFFFFFFF; AddPayloadOctets4(pkt, base::ByteSwap(playback_pos)); } else if (event_ == Event::ADDRESSED_PLAYER_CHANGED) { break; } case Event::PLAYER_APPLICATION_SETTING_CHANGED: break; // No additional data case Event::NOW_PLAYING_CONTENT_CHANGED: break; // No additional data case Event::AVAILABLE_PLAYERS_CHANGED: break; // No additional data case Event::ADDRESSED_PLAYER_CHANGED: { uint16_t uid_counter = data_ & 0xFFFF; uint16_t player_id = (data_ >> 16) & 0xFFFF; AddPayloadOctets2(pkt, base::ByteSwap(player_id)); AddPayloadOctets2(pkt, base::ByteSwap(uid_counter)); } else if (event_ == Event::UIDS_CHANGED) { break; } case Event::UIDS_CHANGED: { uint16_t uid_counter = data_ & 0xFFFF; AddPayloadOctets2(pkt, base::ByteSwap(uid_counter)); break; } default: // TODO (apanicke): Add Volume Changed builder for when we are controller. LOG(FATAL) << "Unhandled event for register notification"; break; } return true; Loading Loading @@ -177,5 +246,33 @@ std::string RegisterNotificationRequest::ToString() const { return ss.str(); } std::unique_ptr<RegisterNotificationRequestBuilder> RegisterNotificationRequestBuilder::MakeBuilder(Event event, uint32_t interval) { std::unique_ptr<RegisterNotificationRequestBuilder> builder( new RegisterNotificationRequestBuilder(event, interval)); return builder; } size_t RegisterNotificationRequestBuilder::size() const { return RegisterNotificationRequest::kMinSize(); } bool RegisterNotificationRequestBuilder::Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) { ReserveSpace(pkt, size()); PacketBuilder::PushHeader(pkt); VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize()); AddPayloadOctets1(pkt, static_cast<uint8_t>(event_)); AddPayloadOctets4(pkt, base::ByteSwap(interval_)); return true; } } // namespace avrcp } // namespace bluetooth No newline at end of file system/packet/avrcp/register_notification_packet.h +58 −3 Original line number Diff line number Diff line Loading @@ -21,17 +21,50 @@ namespace bluetooth { namespace avrcp { class RegisterNotificationResponse : public VendorPacket { public: virtual ~RegisterNotificationResponse() = default; /** * Register Notificaiton Request Packet Layout * AvrcpPacket: * CType c_type_; * uint8_t subunit_type_ : 5; * uint8_t subunit_id_ : 3; * Opcode opcode_; * VendorPacket: * uint8_t company_id[3]; * uint8_t command_pdu; * uint8_t packet_type; * uint16_t param_length; * RegisterNotificationRequestPacket: * uint8_t event_id; * uint8_t[] data; // Length changes based on the event_id */ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; } // TODO (apanicke): Add other getters when implementing AVRCP Controller bool IsInterim() const; Event GetEvent() const; uint8_t GetVolume() const; virtual bool IsValid() const override; virtual std::string ToString() const override; protected: using VendorPacket::VendorPacket; }; class RegisterNotificationResponseBuilder : public VendorPacketBuilder { public: virtual ~RegisterNotificationResponseBuilder() = default; // Playback Status Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakePlaybackStatusBuilder(bool interim, uint8_t play_status); // Track Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakeTrackChangedBuilder(bool interim, uint64_t track_uid); // Playback Position Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakePlaybackPositionBuilder(bool interim, uint32_t playback_pos); Loading Loading @@ -97,5 +130,27 @@ class RegisterNotificationRequest : public VendorPacket { using VendorPacket::VendorPacket; }; class RegisterNotificationRequestBuilder : public VendorPacketBuilder { public: virtual ~RegisterNotificationRequestBuilder() = default; static std::unique_ptr<RegisterNotificationRequestBuilder> MakeBuilder( Event event, uint32_t interval); virtual size_t size() const override; virtual bool Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) override; protected: Event event_; uint32_t interval_; RegisterNotificationRequestBuilder(Event event, uint32_t interval) : VendorPacketBuilder(CType::NOTIFY, CommandPdu::REGISTER_NOTIFICATION, PacketType::SINGLE), event_(event), interval_(interval){}; }; } // namespace avrcp } // namespace bluetooth No newline at end of file Loading
system/packet/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_test { "tests/avrcp/pass_through_packet_test.cc", "tests/avrcp/play_item_packet_test.cc", "tests/avrcp/register_notification_packet_test.cc", "tests/avrcp/set_absolute_volume_packet_test.cc", "tests/avrcp/set_browsed_player_packet_test.cc", "tests/avrcp/vendor_packet_test.cc", "tests/base/iterator_test.cc", Loading
system/packet/avrcp/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ cc_library_static { "pass_through_packet.cc", "play_item.cc", "register_notification_packet.cc", "set_absolute_volume.cc", "set_browsed_player.cc", "vendor_packet.cc", ], Loading
system/packet/avrcp/avrcp_common.h +1 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ enum class CommandPdu : uint8_t { GET_ELEMENT_ATTRIBUTES = 0x20, GET_PLAY_STATUS = 0x30, REGISTER_NOTIFICATION = 0x31, SET_ABSOLUTE_VOLUME = 0x50, SET_ADDRESSED_PLAYER = 0x60, PLAY_ITEM = 0x74, }; Loading
system/packet/avrcp/register_notification_packet.cc +113 −16 Original line number Diff line number Diff line Loading @@ -21,6 +21,54 @@ namespace bluetooth { namespace avrcp { bool RegisterNotificationResponse::IsInterim() const { return GetCType() == CType::INTERIM; } Event RegisterNotificationResponse::GetEvent() const { auto value = *(begin() + VendorPacket::kMinSize()); return static_cast<Event>(value); } uint8_t RegisterNotificationResponse::GetVolume() const { CHECK(GetEvent() == Event::VOLUME_CHANGED); auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1); return *it; } bool RegisterNotificationResponse::IsValid() const { if (!VendorPacket::IsValid()) return false; if (size() < kMinSize()) return false; if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED) return false; switch (GetEvent()) { case Event::VOLUME_CHANGED: return size() == (kMinSize() + 1); default: // TODO (apanicke): Add the remaining events when implementing AVRCP // Controller return false; } } std::string RegisterNotificationResponse::ToString() const { std::stringstream ss; ss << "RegisterNotificationResponse: " << std::endl; ss << " └ cType = " << GetCType() << std::endl; ss << " └ Subunit Type = " << loghex(GetSubunitType()) << std::endl; ss << " └ Subunit ID = " << loghex(GetSubunitId()) << std::endl; ss << " └ OpCode = " << GetOpcode() << std::endl; ss << " └ Company ID = " << loghex(GetCompanyId()) << std::endl; ss << " └ Command PDU = " << GetCommandPdu() << std::endl; ss << " └ PacketType = " << GetPacketType() << std::endl; ss << " └ Parameter Length = " << loghex(GetParameterLength()) << std::endl; ss << " └ Event Registered = " << GetEvent() << std::endl; ss << std::endl; return ss.str(); } std::unique_ptr<RegisterNotificationResponseBuilder> RegisterNotificationResponseBuilder::MakePlaybackStatusBuilder( bool interim, uint8_t play_status) { Loading Loading @@ -124,22 +172,43 @@ bool RegisterNotificationResponseBuilder::Serialize( VendorPacketBuilder::PushHeader(pkt, 1 + data_size); AddPayloadOctets1(pkt, static_cast<uint8_t>(event_)); if (event_ == Event::PLAYBACK_STATUS_CHANGED) { switch (event_) { case Event::PLAYBACK_STATUS_CHANGED: { uint8_t playback_status = data_ & 0xFF; AddPayloadOctets1(pkt, playback_status); } else if (event_ == Event::TRACK_CHANGED) { break; } case Event::TRACK_CHANGED: { AddPayloadOctets8(pkt, base::ByteSwap(data_)); } else if (event_ == Event::PLAYBACK_POS_CHANGED) { break; } case Event::PLAYBACK_POS_CHANGED: { uint32_t playback_pos = data_ & 0xFFFFFFFF; AddPayloadOctets4(pkt, base::ByteSwap(playback_pos)); } else if (event_ == Event::ADDRESSED_PLAYER_CHANGED) { break; } case Event::PLAYER_APPLICATION_SETTING_CHANGED: break; // No additional data case Event::NOW_PLAYING_CONTENT_CHANGED: break; // No additional data case Event::AVAILABLE_PLAYERS_CHANGED: break; // No additional data case Event::ADDRESSED_PLAYER_CHANGED: { uint16_t uid_counter = data_ & 0xFFFF; uint16_t player_id = (data_ >> 16) & 0xFFFF; AddPayloadOctets2(pkt, base::ByteSwap(player_id)); AddPayloadOctets2(pkt, base::ByteSwap(uid_counter)); } else if (event_ == Event::UIDS_CHANGED) { break; } case Event::UIDS_CHANGED: { uint16_t uid_counter = data_ & 0xFFFF; AddPayloadOctets2(pkt, base::ByteSwap(uid_counter)); break; } default: // TODO (apanicke): Add Volume Changed builder for when we are controller. LOG(FATAL) << "Unhandled event for register notification"; break; } return true; Loading Loading @@ -177,5 +246,33 @@ std::string RegisterNotificationRequest::ToString() const { return ss.str(); } std::unique_ptr<RegisterNotificationRequestBuilder> RegisterNotificationRequestBuilder::MakeBuilder(Event event, uint32_t interval) { std::unique_ptr<RegisterNotificationRequestBuilder> builder( new RegisterNotificationRequestBuilder(event, interval)); return builder; } size_t RegisterNotificationRequestBuilder::size() const { return RegisterNotificationRequest::kMinSize(); } bool RegisterNotificationRequestBuilder::Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) { ReserveSpace(pkt, size()); PacketBuilder::PushHeader(pkt); VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize()); AddPayloadOctets1(pkt, static_cast<uint8_t>(event_)); AddPayloadOctets4(pkt, base::ByteSwap(interval_)); return true; } } // namespace avrcp } // namespace bluetooth No newline at end of file
system/packet/avrcp/register_notification_packet.h +58 −3 Original line number Diff line number Diff line Loading @@ -21,17 +21,50 @@ namespace bluetooth { namespace avrcp { class RegisterNotificationResponse : public VendorPacket { public: virtual ~RegisterNotificationResponse() = default; /** * Register Notificaiton Request Packet Layout * AvrcpPacket: * CType c_type_; * uint8_t subunit_type_ : 5; * uint8_t subunit_id_ : 3; * Opcode opcode_; * VendorPacket: * uint8_t company_id[3]; * uint8_t command_pdu; * uint8_t packet_type; * uint16_t param_length; * RegisterNotificationRequestPacket: * uint8_t event_id; * uint8_t[] data; // Length changes based on the event_id */ static constexpr size_t kMinSize() { return VendorPacket::kMinSize() + 1; } // TODO (apanicke): Add other getters when implementing AVRCP Controller bool IsInterim() const; Event GetEvent() const; uint8_t GetVolume() const; virtual bool IsValid() const override; virtual std::string ToString() const override; protected: using VendorPacket::VendorPacket; }; class RegisterNotificationResponseBuilder : public VendorPacketBuilder { public: virtual ~RegisterNotificationResponseBuilder() = default; // Playback Status Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakePlaybackStatusBuilder(bool interim, uint8_t play_status); // Track Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakeTrackChangedBuilder(bool interim, uint64_t track_uid); // Playback Position Changed Maker static std::unique_ptr<RegisterNotificationResponseBuilder> MakePlaybackPositionBuilder(bool interim, uint32_t playback_pos); Loading Loading @@ -97,5 +130,27 @@ class RegisterNotificationRequest : public VendorPacket { using VendorPacket::VendorPacket; }; class RegisterNotificationRequestBuilder : public VendorPacketBuilder { public: virtual ~RegisterNotificationRequestBuilder() = default; static std::unique_ptr<RegisterNotificationRequestBuilder> MakeBuilder( Event event, uint32_t interval); virtual size_t size() const override; virtual bool Serialize( const std::shared_ptr<::bluetooth::Packet>& pkt) override; protected: Event event_; uint32_t interval_; RegisterNotificationRequestBuilder(Event event, uint32_t interval) : VendorPacketBuilder(CType::NOTIFY, CommandPdu::REGISTER_NOTIFICATION, PacketType::SINGLE), event_(event), interval_(interval){}; }; } // namespace avrcp } // namespace bluetooth No newline at end of file