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