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