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