• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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