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