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