1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <iostream> 20 #include <memory> 21 #include <stack> 22 23 #include <base/bind.h> 24 #include <base/cancelable_callback.h> 25 26 #include "avrcp_internal.h" 27 #include "hardware/avrcp/avrcp.h" 28 #include "packet/avrcp/avrcp_browse_packet.h" 29 #include "packet/avrcp/avrcp_packet.h" 30 #include "packet/avrcp/capabilities_packet.h" 31 #include "packet/avrcp/change_path.h" 32 #include "packet/avrcp/get_element_attributes_packet.h" 33 #include "packet/avrcp/get_folder_items.h" 34 #include "packet/avrcp/get_item_attributes.h" 35 #include "packet/avrcp/get_total_number_of_items.h" 36 #include "packet/avrcp/play_item.h" 37 #include "packet/avrcp/register_notification_packet.h" 38 #include "packet/avrcp/set_addressed_player.h" 39 #include "packet/avrcp/set_browsed_player.h" 40 #include "packet/avrcp/vendor_packet.h" 41 #include "profile/avrcp/media_id_map.h" 42 #include "raw_address.h" 43 44 namespace bluetooth { 45 namespace avrcp { 46 47 /** 48 * A class representing a connection with a remote AVRCP device. It holds all 49 * the state and message handling for the device that it represents. 50 */ 51 // TODO (apanicke): Once we move over to having the individual message 52 // responders for Browse and Classic AVRCP Messages move the device around via a 53 // weak pointer. 54 class Device { 55 public: 56 /** 57 * Device is friends with Avrcp::ConnectionHandler so that ConnectionHandler 58 * can deliver messages to individual devices. 59 */ 60 friend class ConnectionHandler; 61 62 Device( 63 const RawAddress& bdaddr, bool avrcp13_compatibility, 64 base::Callback<void(uint8_t label, bool browse, 65 std::unique_ptr<::bluetooth::PacketBuilder> message)> 66 send_msg_cb, 67 uint16_t ctrl_mtu, uint16_t browse_mtu); 68 69 Device(const Device&) = delete; 70 Device& operator=(const Device&) = delete; 71 72 virtual ~Device() = default; 73 74 /** 75 * Gets a weak pointer to this device that is invalidated when the device is 76 * disconnected. 77 */ 78 base::WeakPtr<Device> Get(); 79 GetAddress()80 const RawAddress& GetAddress() const { return address_; }; 81 82 /** 83 * Disconnects the AVRCP connection that this device represents. 84 */ 85 bool Disconnect(); 86 87 /** 88 * Set the status of the BIP obex client 89 */ 90 void SetBipClientStatus(bool connected); 91 92 /** 93 * Returns true if the current device has a BIP OBEX client. 94 */ 95 bool HasBipClient() const; 96 97 /** 98 * Returns true if the current device is silenced. 99 */ 100 bool IsInSilenceMode() const; 101 102 /** 103 * Returns true if the current device is active. 104 */ 105 bool IsActive() const; 106 107 /** 108 * Register the interfaces that the device uses to get information. If the 109 * Volume Interface is null, then absolute volume is disabled. 110 * TODO (apanicke): Add these to the constructor/factory so that each device 111 * is created valid and can't be accidentally interacted with when no 112 * interfaces are registered. 113 */ 114 void RegisterInterfaces(MediaInterface* interface, 115 A2dpInterface* a2dp_interface, 116 VolumeInterface* volume_interface); 117 118 /** 119 * Set the maximum size of a AVRCP Browsing Packet. This is done after the 120 * connection of the Browsing channel. 121 */ 122 void SetBrowseMtu(uint16_t browse_mtu); 123 124 /** 125 * Notify the device that metadata, play_status, and/or queue have updated 126 * via a boolean. Each boolean represents whether its respective content has 127 * updated. 128 */ 129 virtual void SendMediaUpdate(bool metadata, bool play_status, bool queue); 130 131 /** 132 * Notify the device that the available_player, addressed_player, or UIDs 133 * have updated via a boolean. Each boolean represents whether its respective 134 * content has updated. 135 */ 136 virtual void SendFolderUpdate(bool available_player, bool addressed_player, 137 bool uids); 138 139 // TODO (apanicke): Split the message handlers into two files. One 140 // for handling Browse Messages and the other for handling all other 141 // messages. This prevents the .cc file from getting bloated like it is 142 // now. The Device class will then become a state holder for each message 143 // and all the functions in these handler classes can be static since the 144 // device will be passed in. The extensions of the Device class can contain 145 // any interop handling for specific messages on specific devices. 146 147 void MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt); 148 void BrowseMessageReceived(uint8_t label, std::shared_ptr<BrowsePacket> pkt); 149 void VendorPacketHandler(uint8_t label, std::shared_ptr<VendorPacket> pkt); 150 151 /******************** 152 * MESSAGE RESPONSES 153 ********************/ 154 // CURRENT TRACK CHANGED 155 virtual void HandleTrackUpdate(); 156 virtual void TrackChangedNotificationResponse( 157 uint8_t label, bool interim, std::string curr_song_id, 158 std::vector<SongInfo> song_list); 159 160 // GET CAPABILITY 161 virtual void HandleGetCapabilities( 162 uint8_t label, const std::shared_ptr<GetCapabilitiesRequest>& pkt); 163 164 // REGISTER NOTIFICATION 165 virtual void HandleNotification( 166 uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt); 167 168 // PLAY STATUS CHANGED 169 virtual void HandlePlayStatusUpdate(); 170 171 // NOW PLAYING LIST CHANGED 172 virtual void HandleNowPlayingUpdate(); 173 virtual void HandleNowPlayingNotificationResponse( 174 uint8_t label, bool interim, std::string curr_song_id, 175 std::vector<SongInfo> song_list); 176 177 // PLAY POSITION CHANGED 178 virtual void HandlePlayPosUpdate(); 179 virtual void PlaybackPosNotificationResponse(uint8_t label, bool interim, 180 PlayStatus status); 181 182 // GET PLAY STATUS 183 virtual void GetPlayStatusResponse(uint8_t label, PlayStatus status); 184 virtual void PlaybackStatusNotificationResponse(uint8_t label, bool interim, 185 PlayStatus status); 186 187 // GET ELEMENT ATTRIBUTE 188 // TODO (apanicke): Add a Handler function for this so if a specific device 189 // needs to implement an interop fix, you only need to overload the one 190 // function. 191 virtual void GetElementAttributesResponse( 192 uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt, 193 SongInfo info); 194 195 // AVAILABLE PLAYER CHANGED 196 virtual void HandleAvailablePlayerUpdate(); 197 198 // ADDRESSED PLAYER CHANGED 199 virtual void HandleAddressedPlayerUpdate(); 200 virtual void RejectNotification(); 201 virtual void AddressedPlayerNotificationResponse( 202 uint8_t label, bool interim, uint16_t curr_player, 203 std::vector<MediaPlayerInfo> /* unused */); 204 205 // GET FOLDER ITEMS 206 virtual void HandleGetFolderItems( 207 uint8_t label, std::shared_ptr<GetFolderItemsRequest> request); 208 virtual void GetMediaPlayerListResponse( 209 uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt, 210 uint16_t curr_player, std::vector<MediaPlayerInfo> players); 211 virtual void GetVFSListResponse(uint8_t label, 212 std::shared_ptr<GetFolderItemsRequest> pkt, 213 std::vector<ListItem> items); 214 virtual void GetNowPlayingListResponse( 215 uint8_t label, std::shared_ptr<GetFolderItemsRequest> pkt, 216 std::string curr_song_id, std::vector<SongInfo> song_list); 217 218 // GET TOTAL NUMBER OF ITEMS 219 virtual void HandleGetTotalNumberOfItems( 220 uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt); 221 virtual void GetTotalNumberOfItemsMediaPlayersResponse( 222 uint8_t label, uint16_t curr_player, std::vector<MediaPlayerInfo> list); 223 virtual void GetTotalNumberOfItemsVFSResponse(uint8_t label, 224 std::vector<ListItem> items); 225 virtual void GetTotalNumberOfItemsNowPlayingResponse( 226 uint8_t label, std::string curr_song_id, std::vector<SongInfo> song_list); 227 228 // GET ITEM ATTRIBUTES 229 virtual void HandleGetItemAttributes( 230 uint8_t label, std::shared_ptr<GetItemAttributesRequest> request); 231 virtual void GetItemAttributesNowPlayingResponse( 232 uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt, 233 std::string curr_media_id, std::vector<SongInfo> song_list); 234 virtual void GetItemAttributesVFSResponse( 235 uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt, 236 std::vector<ListItem> item_list); 237 238 // SET BROWSED PLAYER 239 virtual void HandleSetBrowsedPlayer( 240 uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> request); 241 virtual void SetBrowsedPlayerResponse( 242 uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt, bool success, 243 std::string root_id, uint32_t num_items); 244 245 // CHANGE PATH 246 virtual void HandleChangePath(uint8_t label, 247 std::shared_ptr<ChangePathRequest> request); 248 virtual void ChangePathResponse(uint8_t label, 249 std::shared_ptr<ChangePathRequest> request, 250 std::vector<ListItem> list); 251 252 // PLAY ITEM 253 virtual void HandlePlayItem(uint8_t label, 254 std::shared_ptr<PlayItemRequest> request); 255 256 // SET ADDRESSED PLAYER 257 virtual void HandleSetAddressedPlayer( 258 uint8_t label, std::shared_ptr<SetAddressedPlayerRequest> request, 259 uint16_t curr_player, std::vector<MediaPlayerInfo> players); 260 261 /******************** 262 * MESSAGE REQUESTS 263 ********************/ 264 // VOLUME CHANGED NOTIFICATION 265 virtual void RegisterVolumeChanged(); 266 virtual void HandleVolumeChanged( 267 uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt); 268 269 // SET VOLUME 270 virtual void SetVolume(int8_t volume); 271 272 /** 273 * This function is called by Avrcp::ConnectionHandler to signify that 274 * the remote device was disconnected. 275 * 276 * TODO (apanicke): Prevent allowing responses to messages while the device is 277 * disconnected by using a weak pointer handle to the device when we separate 278 * out the message handling. Also separate the logic in the future when 279 * disconnecting only browsing (Though this shouldn't matter as if we are 280 * disconnecting browsing then we should be fully disconnecting the device). 281 */ 282 void DeviceDisconnected(); 283 284 friend std::ostream& operator<<(std::ostream& out, const Device& c); 285 286 private: 287 // This should always contain one item which represents the root id on the 288 // current player. CurrentFolder()289 std::string CurrentFolder() const { 290 if (current_path_.empty()) return ""; 291 return current_path_.top(); 292 } 293 send_message(uint8_t label,bool browse,std::unique_ptr<::bluetooth::PacketBuilder> message)294 void send_message(uint8_t label, bool browse, 295 std::unique_ptr<::bluetooth::PacketBuilder> message) { 296 active_labels_.erase(label); 297 send_message_cb_.Run(label, browse, std::move(message)); 298 } 299 base::WeakPtrFactory<Device> weak_ptr_factory_; 300 301 // TODO (apanicke): Initialize all the variables in the constructor. 302 RawAddress address_; 303 304 // Enables AVRCP 1.3 Compatibility mode. This disables any AVRCP 1.4+ features 305 // such as browsing and playlists but has the highest chance of working. 306 bool avrcp13_compatibility_ = false; 307 base::Callback<void(uint8_t label, bool browse, 308 std::unique_ptr<::bluetooth::PacketBuilder> message)> 309 send_message_cb_; 310 uint16_t ctrl_mtu_; 311 uint16_t browse_mtu_; 312 bool has_bip_client_; 313 314 int curr_browsed_player_id_ = -1; 315 316 std::stack<std::string> current_path_; 317 318 // Notification Trackers 319 using Notification = std::pair<bool, uint8_t>; 320 Notification track_changed_ = Notification(false, 0); 321 Notification play_status_changed_ = Notification(false, 0); 322 Notification play_pos_changed_ = Notification(false, 0); 323 Notification now_playing_changed_ = Notification(false, 0); 324 Notification addr_player_changed_ = Notification(false, 0); 325 Notification avail_players_changed_ = Notification(false, 0); 326 Notification uids_changed_ = Notification(false, 0); 327 328 MediaIdMap vfs_ids_; 329 MediaIdMap now_playing_ids_; 330 331 uint32_t play_pos_interval_ = 0; 332 333 SongInfo last_song_info_; 334 PlayStatus last_play_status_; 335 336 base::CancelableClosure play_pos_update_cb_; 337 338 MediaInterface* media_interface_ = nullptr; 339 A2dpInterface* a2dp_interface_ = nullptr; 340 VolumeInterface* volume_interface_ = nullptr; 341 342 // Labels used for messages currently in flight. 343 std::set<uint8_t> active_labels_; 344 345 int8_t volume_ = -1; 346 }; 347 348 } // namespace avrcp 349 } // namespace bluetooth 350