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