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