// // Copyright 2017 Google, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at: // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "service/avrcp_control.h" #include #include #include #include #include #include #include "service/logging_helpers.h" #include "stack/include/avrc_defs.h" namespace bluetooth { AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id) : app_identifier_(uuid), control_id_(control_id) { hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this); } AvrcpControl::~AvrcpControl() { hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this); } const Uuid& AvrcpControl::GetAppIdentifier() const { return app_identifier_; } int AvrcpControl::GetInstanceId() const { return control_id_; } void AvrcpControl::SetDelegate(Delegate* delegate) { std::lock_guard lock(delegate_mutex_); delegate_ = delegate; } bool AvrcpControl::Enable() { std::lock_guard lock(mutex_); return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable(); } void AvrcpControl::Disable() { std::lock_guard lock(mutex_); hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable(); } bool AvrcpControl::SendPassThroughCommand(const std::string& device_address, uint8_t key_code, bool key_pressed) { RawAddress addr; if (!RawAddress::FromString(device_address, addr)) { LOG(ERROR) << "Invalid device address given: " << device_address; return false; } uint8_t key_state = key_pressed ? AVRC_STATE_PRESS : AVRC_STATE_RELEASE; bt_status_t status; { std::lock_guard lock(mutex_); status = hal::BluetoothAvrcpInterface::Get() ->GetControlHALInterface() ->send_pass_through_cmd(addr, key_code, key_state); } if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to send passthrough command"; return false; } return true; } bool AvrcpControl::SetAbsVolumeResponse(const std::string& device_address, int32_t abs_vol, int32_t label) { RawAddress addr; if (!RawAddress::FromString(device_address, addr)) { LOG(ERROR) << "Invalid device address given: " << device_address; return false; } bt_status_t status; { std::lock_guard lock(mutex_); status = hal::BluetoothAvrcpInterface::Get() ->GetControlHALInterface() ->set_volume_rsp(addr, abs_vol, label); } if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to send set absolute volume response"; return false; } return true; } bool AvrcpControl::RegisterForAbsVolumeCallbackResponse( const std::string& device_address, int32_t response_type, int32_t abs_vol, int32_t label) { RawAddress addr; if (!RawAddress::FromString(device_address, addr)) { LOG(ERROR) << "Invalid device address given: " << device_address; return false; } bt_status_t status; { std::lock_guard lock(mutex_); status = hal::BluetoothAvrcpInterface::Get() ->GetControlHALInterface() ->register_abs_vol_rsp( addr, static_cast(response_type), abs_vol, label); } if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to send send register for absolute volume change callback"; return false; } return true; } void AvrcpControl::ConnectionStateCallback(bool rc_connect, bool bt_connect, const RawAddress& bd_addr) { std::string device_address = BtAddrString(&bd_addr); std::lock_guard lock(delegate_mutex_); if (delegate_) delegate_->OnConnectionState(rc_connect, bt_connect, device_address); } void AvrcpControl::CtrlSetabsvolCmdCallback(const RawAddress& bd_addr, uint8_t abs_vol, uint8_t label) { std::string device_address = BtAddrString(&bd_addr); std::lock_guard lock(delegate_mutex_); if (delegate_) delegate_->OnSetAbsVolumeRequest(device_address, abs_vol, label); } void AvrcpControl::CtrlRegisternotificationAbsVolCallback( const RawAddress& bd_addr, uint8_t label) { std::string device_address = BtAddrString(&bd_addr); std::lock_guard lock(delegate_mutex_); if (delegate_) delegate_->OnRegisterForAbsVolumeCallbackRequest(device_address, label); } void AvrcpControl::CtrlTrackChangedCallback(const RawAddress& bd_addr, uint8_t num_attr, btrc_element_attr_val_t* p_attrs) { std::string device_address = BtAddrString(&bd_addr); std::string title; std::string artist; std::string album; std::string genre; int track_num = -1; int num_tracks = -1; int play_time = -1; for (size_t i = 0; i < num_attr; ++i) { auto attr_text = reinterpret_cast(p_attrs[i].text); switch (p_attrs[i].attr_id) { case BTRC_MEDIA_ATTR_ID_TITLE: title = attr_text; break; case BTRC_MEDIA_ATTR_ID_ARTIST: artist = attr_text; break; case BTRC_MEDIA_ATTR_ID_ALBUM: album = attr_text; break; case BTRC_MEDIA_ATTR_ID_TRACK_NUM: if (!base::StringToInt(attr_text, &track_num)) { LOG(ERROR) << "Failed to parse track number"; } break; case BTRC_MEDIA_ATTR_ID_NUM_TRACKS: if (!base::StringToInt(attr_text, &num_tracks)) { LOG(ERROR) << "Failed to parse number of tracks"; } break; case BTRC_MEDIA_ATTR_ID_GENRE: genre = attr_text; break; case BTRC_MEDIA_ATTR_ID_PLAYING_TIME: if (!base::StringToInt(attr_text, &play_time)) { LOG(ERROR) << "Failed to parse playing time"; } break; default: NOTREACHED(); } } const AvrcpMediaAttr attr(title, artist, album, genre, track_num, num_tracks, play_time); std::lock_guard lock(delegate_mutex_); if (delegate_) delegate_->OnTrackChanged(device_address, attr); } // AvrcpControlFactory implementation // ======================================================== AvrcpControlFactory::AvrcpControlFactory() = default; AvrcpControlFactory::~AvrcpControlFactory() = default; bool AvrcpControlFactory::RegisterInstance(const Uuid& uuid, const RegisterCallback& callback) { VLOG(1) << __func__ << " - Uuid: " << uuid.ToString(); int control_id = next_control_id_++; std::unique_ptr hf_client(new AvrcpControl(uuid, control_id)); callback(BLE_STATUS_SUCCESS, uuid, std::move(hf_client)); return true; } } // namespace bluetooth