2 // Copyright 2017 Google, Inc.
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:
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "service/avrcp_control.h"
23 #include <base/logging.h>
24 #include <base/memory/ptr_util.h>
25 #include <base/strings/string_number_conversions.h>
27 #include "service/logging_helpers.h"
29 #include "stack/include/avrc_defs.h"
34 AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id)
35 : app_identifier_(uuid), control_id_(control_id) {
36 hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this);
39 AvrcpControl::~AvrcpControl() {
40 hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this);
43 const Uuid& AvrcpControl::GetAppIdentifier() const { return app_identifier_; }
45 int AvrcpControl::GetInstanceId() const { return control_id_; }
47 void AvrcpControl::SetDelegate(Delegate* delegate) {
48 std::lock_guard<std::mutex> lock(delegate_mutex_);
52 bool AvrcpControl::Enable() {
53 std::lock_guard<std::mutex> lock(mutex_);
54 return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable();
57 void AvrcpControl::Disable() {
58 std::lock_guard<std::mutex> lock(mutex_);
59 hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable();
62 bool AvrcpControl::SendPassThroughCommand(const std::string& device_address,
63 uint8_t key_code, bool key_pressed) {
65 if (!RawAddress::FromString(device_address, addr)) {
66 LOG(ERROR) << "Invalid device address given: " << device_address;
70 uint8_t key_state = key_pressed ? AVRC_STATE_PRESS : AVRC_STATE_RELEASE;
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);
78 if (status != BT_STATUS_SUCCESS) {
79 LOG(ERROR) << "Failed to send passthrough command";
86 bool AvrcpControl::SetAbsVolumeResponse(const std::string& device_address,
87 int32_t abs_vol, int32_t label) {
89 if (!RawAddress::FromString(device_address, addr)) {
90 LOG(ERROR) << "Invalid device address given: " << device_address;
96 std::lock_guard<std::mutex> lock(mutex_);
97 status = hal::BluetoothAvrcpInterface::Get()
98 ->GetControlHALInterface()
99 ->set_volume_rsp(addr, abs_vol, label);
101 if (status != BT_STATUS_SUCCESS) {
102 LOG(ERROR) << "Failed to send set absolute volume response";
109 bool AvrcpControl::RegisterForAbsVolumeCallbackResponse(
110 const std::string& device_address, int32_t response_type, int32_t abs_vol,
113 if (!RawAddress::FromString(device_address, addr)) {
114 LOG(ERROR) << "Invalid device address given: " << device_address;
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),
127 if (status != BT_STATUS_SUCCESS) {
129 << "Failed to send send register for absolute volume change callback";
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_);
141 delegate_->OnConnectionState(rc_connect, bt_connect, device_address);
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_);
149 delegate_->OnSetAbsVolumeRequest(device_address, abs_vol, 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_);
157 delegate_->OnRegisterForAbsVolumeCallbackRequest(device_address, label);
160 void AvrcpControl::CtrlTrackChangedCallback(const RawAddress& bd_addr,
162 btrc_element_attr_val_t* p_attrs) {
163 std::string device_address = BtAddrString(&bd_addr);
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:
179 case BTRC_MEDIA_ATTR_ID_ARTIST:
182 case BTRC_MEDIA_ATTR_ID_ALBUM:
185 case BTRC_MEDIA_ATTR_ID_TRACK_NUM:
186 if (!base::StringToInt(attr_text, &track_num)) {
187 LOG(ERROR) << "Failed to parse track number";
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";
195 case BTRC_MEDIA_ATTR_ID_GENRE:
198 case BTRC_MEDIA_ATTR_ID_PLAYING_TIME:
199 if (!base::StringToInt(attr_text, &play_time)) {
200 LOG(ERROR) << "Failed to parse playing time";
208 const AvrcpMediaAttr attr(title, artist, album, genre, track_num, num_tracks,
211 std::lock_guard<std::mutex> lock(delegate_mutex_);
212 if (delegate_) delegate_->OnTrackChanged(device_address, attr);
215 // AvrcpControlFactory implementation
216 // ========================================================
218 AvrcpControlFactory::AvrcpControlFactory() = default;
219 AvrcpControlFactory::~AvrcpControlFactory() = default;
221 bool AvrcpControlFactory::RegisterInstance(const Uuid& uuid,
222 const RegisterCallback& callback) {
223 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
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));
231 } // namespace bluetooth