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