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