1 //
2 //  Copyright 2017 Google, Inc.
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 #include "service/avrcp_control.h"
18 
19 #include <cerrno>
20 #include <climits>
21 #include <string>
22 
23 #include <base/logging.h>
24 #include <base/memory/ptr_util.h>
25 #include <base/strings/string_number_conversions.h>
26 
27 #include "service/logging_helpers.h"
28 
29 #include "stack/include/avrc_defs.h"
30 
31 
32 namespace bluetooth {
33 
AvrcpControl(const Uuid & uuid,int control_id)34 AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id)
35     : app_identifier_(uuid), control_id_(control_id) {
36   hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this);
37 }
38 
~AvrcpControl()39 AvrcpControl::~AvrcpControl() {
40   hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this);
41 }
42 
GetAppIdentifier() const43 const Uuid& AvrcpControl::GetAppIdentifier() const { return app_identifier_; }
44 
GetInstanceId() const45 int AvrcpControl::GetInstanceId() const { return control_id_; }
46 
SetDelegate(Delegate * delegate)47 void AvrcpControl::SetDelegate(Delegate* delegate) {
48   std::lock_guard<std::mutex> lock(delegate_mutex_);
49   delegate_ = delegate;
50 }
51 
Enable()52 bool AvrcpControl::Enable() {
53   std::lock_guard<std::mutex> lock(mutex_);
54   return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable();
55 }
56 
Disable()57 void AvrcpControl::Disable() {
58   std::lock_guard<std::mutex> lock(mutex_);
59   hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable();
60 }
61 
SendPassThroughCommand(const std::string & device_address,uint8_t key_code,bool key_pressed)62 bool AvrcpControl::SendPassThroughCommand(const std::string& device_address,
63                                           uint8_t key_code, bool key_pressed) {
64   RawAddress addr;
65   if (!RawAddress::FromString(device_address, addr)) {
66     LOG(ERROR) << "Invalid device address given: " << device_address;
67     return false;
68   }
69 
70   uint8_t key_state = key_pressed ? AVRC_STATE_PRESS : AVRC_STATE_RELEASE;
71   bt_status_t status;
72   {
73     std::lock_guard<std::mutex> lock(mutex_);
74     status = hal::BluetoothAvrcpInterface::Get()
75                  ->GetControlHALInterface()
76                  ->send_pass_through_cmd(addr, key_code, key_state);
77   }
78   if (status != BT_STATUS_SUCCESS) {
79     LOG(ERROR) << "Failed to send passthrough command";
80     return false;
81   }
82 
83   return true;
84 }
85 
SetAbsVolumeResponse(const std::string & device_address,int32_t abs_vol,int32_t label)86 bool AvrcpControl::SetAbsVolumeResponse(const std::string& device_address,
87                                         int32_t abs_vol, int32_t label) {
88   RawAddress addr;
89   if (!RawAddress::FromString(device_address, addr)) {
90     LOG(ERROR) << "Invalid device address given: " << device_address;
91     return false;
92   }
93 
94   bt_status_t status;
95   {
96     std::lock_guard<std::mutex> lock(mutex_);
97     status = hal::BluetoothAvrcpInterface::Get()
98                  ->GetControlHALInterface()
99                  ->set_volume_rsp(addr, abs_vol, label);
100   }
101   if (status != BT_STATUS_SUCCESS) {
102     LOG(ERROR) << "Failed to send set absolute volume response";
103     return false;
104   }
105 
106   return true;
107 }
108 
RegisterForAbsVolumeCallbackResponse(const std::string & device_address,int32_t response_type,int32_t abs_vol,int32_t label)109 bool AvrcpControl::RegisterForAbsVolumeCallbackResponse(
110     const std::string& device_address, int32_t response_type, int32_t abs_vol,
111     int32_t label) {
112   RawAddress addr;
113   if (!RawAddress::FromString(device_address, addr)) {
114     LOG(ERROR) << "Invalid device address given: " << device_address;
115     return false;
116   }
117 
118   bt_status_t status;
119   {
120     std::lock_guard<std::mutex> lock(mutex_);
121     status = hal::BluetoothAvrcpInterface::Get()
122                  ->GetControlHALInterface()
123                  ->register_abs_vol_rsp(
124                      addr, static_cast<btrc_notification_type_t>(response_type),
125                      abs_vol, label);
126   }
127   if (status != BT_STATUS_SUCCESS) {
128     LOG(ERROR)
129         << "Failed to send send register for absolute volume change callback";
130     return false;
131   }
132 
133   return true;
134 }
135 
ConnectionStateCallback(bool rc_connect,bool bt_connect,const RawAddress & bd_addr)136 void AvrcpControl::ConnectionStateCallback(bool rc_connect, bool bt_connect,
137                                            const RawAddress& bd_addr) {
138   std::string device_address = BtAddrString(&bd_addr);
139   std::lock_guard<std::mutex> lock(delegate_mutex_);
140   if (delegate_)
141     delegate_->OnConnectionState(rc_connect, bt_connect, device_address);
142 }
143 
CtrlSetabsvolCmdCallback(const RawAddress & bd_addr,uint8_t abs_vol,uint8_t label)144 void AvrcpControl::CtrlSetabsvolCmdCallback(const RawAddress& bd_addr,
145                                             uint8_t abs_vol, uint8_t label) {
146   std::string device_address = BtAddrString(&bd_addr);
147   std::lock_guard<std::mutex> lock(delegate_mutex_);
148   if (delegate_)
149     delegate_->OnSetAbsVolumeRequest(device_address, abs_vol, label);
150 }
151 
CtrlRegisternotificationAbsVolCallback(const RawAddress & bd_addr,uint8_t label)152 void AvrcpControl::CtrlRegisternotificationAbsVolCallback(
153     const RawAddress& bd_addr, uint8_t label) {
154   std::string device_address = BtAddrString(&bd_addr);
155   std::lock_guard<std::mutex> lock(delegate_mutex_);
156   if (delegate_)
157     delegate_->OnRegisterForAbsVolumeCallbackRequest(device_address, label);
158 }
159 
CtrlTrackChangedCallback(const RawAddress & bd_addr,uint8_t num_attr,btrc_element_attr_val_t * p_attrs)160 void AvrcpControl::CtrlTrackChangedCallback(const RawAddress& bd_addr,
161                                             uint8_t num_attr,
162                                             btrc_element_attr_val_t* p_attrs) {
163   std::string device_address = BtAddrString(&bd_addr);
164 
165   std::string title;
166   std::string artist;
167   std::string album;
168   std::string genre;
169   int track_num = -1;
170   int num_tracks = -1;
171   int play_time = -1;
172 
173   for (size_t i = 0; i < num_attr; ++i) {
174     auto attr_text = reinterpret_cast<char*>(p_attrs[i].text);
175     switch (p_attrs[i].attr_id) {
176       case BTRC_MEDIA_ATTR_ID_TITLE:
177         title = attr_text;
178         break;
179       case BTRC_MEDIA_ATTR_ID_ARTIST:
180         artist = attr_text;
181         break;
182       case BTRC_MEDIA_ATTR_ID_ALBUM:
183         album = attr_text;
184         break;
185       case BTRC_MEDIA_ATTR_ID_TRACK_NUM:
186         if (!base::StringToInt(attr_text, &track_num)) {
187           LOG(ERROR) << "Failed to parse track number";
188         }
189         break;
190       case BTRC_MEDIA_ATTR_ID_NUM_TRACKS:
191         if (!base::StringToInt(attr_text, &num_tracks)) {
192           LOG(ERROR) << "Failed to parse number of tracks";
193         }
194         break;
195       case BTRC_MEDIA_ATTR_ID_GENRE:
196         genre = attr_text;
197         break;
198       case BTRC_MEDIA_ATTR_ID_PLAYING_TIME:
199         if (!base::StringToInt(attr_text, &play_time)) {
200           LOG(ERROR) << "Failed to parse playing time";
201         }
202         break;
203       default:
204         NOTREACHED();
205     }
206   }
207 
208   const AvrcpMediaAttr attr(title, artist, album, genre, track_num, num_tracks,
209                             play_time);
210 
211   std::lock_guard<std::mutex> lock(delegate_mutex_);
212   if (delegate_) delegate_->OnTrackChanged(device_address, attr);
213 }
214 
215 // AvrcpControlFactory implementation
216 // ========================================================
217 
218 AvrcpControlFactory::AvrcpControlFactory() = default;
219 AvrcpControlFactory::~AvrcpControlFactory() = default;
220 
RegisterInstance(const Uuid & uuid,const RegisterCallback & callback)221 bool AvrcpControlFactory::RegisterInstance(const Uuid& uuid,
222                                            const RegisterCallback& callback) {
223   VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
224 
225   int control_id = next_control_id_++;
226   std::unique_ptr<AvrcpControl> hf_client(new AvrcpControl(uuid, control_id));
227   callback(BLE_STATUS_SUCCESS, uuid, std::move(hf_client));
228   return true;
229 }
230 
231 }  // namespace bluetooth
232