blob: 18dc2aa9e60b7d0f800a9c5829f19f349fd5a5e6 [file] [log] [blame]
Bailey Forrest62aa15f2017-01-30 17:38:58 -08001//
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
Bailey Forrest62aa15f2017-01-30 17:38:58 -080031
32namespace bluetooth {
33
34AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id)
35 : app_identifier_(uuid), control_id_(control_id) {
36 hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this);
37}
38
39AvrcpControl::~AvrcpControl() {
40 hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this);
41}
42
43const Uuid& AvrcpControl::GetAppIdentifier() const { return app_identifier_; }
44
45int AvrcpControl::GetInstanceId() const { return control_id_; }
46
47void AvrcpControl::SetDelegate(Delegate* delegate) {
48 std::lock_guard<std::mutex> lock(delegate_mutex_);
49 delegate_ = delegate;
50}
51
52bool AvrcpControl::Enable() {
53 std::lock_guard<std::mutex> lock(mutex_);
54 return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable();
55}
56
57void AvrcpControl::Disable() {
58 std::lock_guard<std::mutex> lock(mutex_);
59 hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable();
60}
61
62bool 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
86bool 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
109bool 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
136void 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
144void 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
152void 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
160void 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
Jakub Pawlowski7b00a3b2018-10-23 21:54:53 +0200165 std::string title;
166 std::string artist;
167 std::string album;
168 std::string genre;
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800169 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:
Jakub Pawlowski7b00a3b2018-10-23 21:54:53 +0200177 title = attr_text;
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800178 break;
179 case BTRC_MEDIA_ATTR_ID_ARTIST:
Jakub Pawlowski7b00a3b2018-10-23 21:54:53 +0200180 artist = attr_text;
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800181 break;
182 case BTRC_MEDIA_ATTR_ID_ALBUM:
Jakub Pawlowski7b00a3b2018-10-23 21:54:53 +0200183 album = attr_text;
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800184 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:
Jakub Pawlowski7b00a3b2018-10-23 21:54:53 +0200196 genre = attr_text;
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800197 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
218AvrcpControlFactory::AvrcpControlFactory() = default;
219AvrcpControlFactory::~AvrcpControlFactory() = default;
220
221bool 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