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