1// Copyright 2016 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15 16// Implementation of brillo_audio_client.h 17 18#include "brillo_audio_client.h" 19 20#include <base/logging.h> 21#include <binder/Status.h> 22#include <binderwrapper/binder_wrapper.h> 23 24#include "brillo_audio_client_helpers.h" 25#include "brillo_audio_device_info_def.h" 26#include "brillo_audio_device_info_internal.h" 27 28using android::binder::Status; 29 30namespace brillo { 31 32static const char kBrilloAudioServiceName[] = 33 "android.brillo.brilloaudioservice.BrilloAudioService"; 34 35std::shared_ptr<BrilloAudioClient> BrilloAudioClient::instance_ = nullptr; 36 37int BrilloAudioClient::callback_id_counter_ = 1; 38 39BrilloAudioClient::~BrilloAudioClient() {} 40 41std::weak_ptr<BrilloAudioClient> BrilloAudioClient::GetClientInstance() { 42 if (!instance_) { 43 instance_ = std::shared_ptr<BrilloAudioClient>(new BrilloAudioClient()); 44 if (!instance_->Initialize()) { 45 LOG(ERROR) << "Could not Initialize the brillo audio client."; 46 instance_.reset(); 47 return instance_; 48 } 49 } 50 return instance_; 51} 52 53android::sp<android::IBinder> BrilloAudioClient::ConnectToService( 54 const std::string& service_name, const base::Closure& callback) { 55 android::BinderWrapper* binder_wrapper = 56 android::BinderWrapper::GetOrCreateInstance(); 57 auto service = binder_wrapper->GetService(service_name); 58 if (!service.get()) { 59 return service; 60 } 61 binder_wrapper->RegisterForDeathNotifications(service, callback); 62 return service; 63} 64 65void BrilloAudioClient::OnBASDisconnect() { 66 LOG(WARNING) << "The brillo audio service died! Please reset the " 67 << "BAudioManager."; 68 instance_.reset(); 69} 70 71bool BrilloAudioClient::Initialize() { 72 auto service = ConnectToService( 73 kBrilloAudioServiceName, base::Bind(&BrilloAudioClient::OnBASDisconnect, 74 weak_ptr_factory_.GetWeakPtr())); 75 if (!service.get()) { 76 LOG(ERROR) << "Could not connect to brillo audio service."; 77 return false; 78 } 79 brillo_audio_service_ = android::interface_cast<IBrilloAudioService>(service); 80 return true; 81} 82 83int BrilloAudioClient::GetDevices(int flag, std::vector<int>& devices) { 84 if (!brillo_audio_service_.get()) { 85 OnBASDisconnect(); 86 return ECONNABORTED; 87 } 88 auto status = brillo_audio_service_->GetDevices(flag, &devices); 89 return status.serviceSpecificErrorCode(); 90} 91 92int BrilloAudioClient::SetDevice(audio_policy_force_use_t usage, 93 audio_policy_forced_cfg_t config) { 94 if (!brillo_audio_service_.get()) { 95 OnBASDisconnect(); 96 return ECONNABORTED; 97 } 98 auto status = brillo_audio_service_->SetDevice(usage, config); 99 return status.serviceSpecificErrorCode(); 100} 101 102int BrilloAudioClient::GetMaxVolumeSteps(BAudioUsage usage, int* max_steps) { 103 if (!brillo_audio_service_.get()) { 104 OnBASDisconnect(); 105 return ECONNABORTED; 106 } 107 auto status = brillo_audio_service_->GetMaxVolumeSteps( 108 BrilloAudioClientHelpers::GetStreamType(usage), max_steps); 109 return status.serviceSpecificErrorCode(); 110} 111 112int BrilloAudioClient::SetMaxVolumeSteps(BAudioUsage usage, int max_steps) { 113 if (!brillo_audio_service_.get()) { 114 OnBASDisconnect(); 115 return ECONNABORTED; 116 } 117 auto status = brillo_audio_service_->SetMaxVolumeSteps( 118 BrilloAudioClientHelpers::GetStreamType(usage), max_steps); 119 return status.serviceSpecificErrorCode(); 120} 121 122int BrilloAudioClient::SetVolumeIndex(BAudioUsage usage, 123 audio_devices_t device, 124 int index) { 125 if (!brillo_audio_service_.get()) { 126 OnBASDisconnect(); 127 return ECONNABORTED; 128 } 129 auto status = brillo_audio_service_->SetVolumeIndex( 130 BrilloAudioClientHelpers::GetStreamType(usage), device, index); 131 return status.serviceSpecificErrorCode(); 132} 133 134int BrilloAudioClient::GetVolumeIndex(BAudioUsage usage, 135 audio_devices_t device, 136 int* index) { 137 if (!brillo_audio_service_.get()) { 138 OnBASDisconnect(); 139 return ECONNABORTED; 140 } 141 auto status = brillo_audio_service_->GetVolumeIndex( 142 BrilloAudioClientHelpers::GetStreamType(usage), device, index); 143 return status.serviceSpecificErrorCode(); 144} 145 146int BrilloAudioClient::GetVolumeControlStream(BAudioUsage* usage) { 147 if (!brillo_audio_service_.get()) { 148 OnBASDisconnect(); 149 return ECONNABORTED; 150 } 151 int stream; 152 auto status = brillo_audio_service_->GetVolumeControlStream(&stream); 153 *usage = BrilloAudioClientHelpers::GetBAudioUsage( 154 static_cast<audio_stream_type_t>(stream)); 155 return status.serviceSpecificErrorCode(); 156} 157 158int BrilloAudioClient::SetVolumeControlStream(BAudioUsage usage) { 159 if (!brillo_audio_service_.get()) { 160 OnBASDisconnect(); 161 return ECONNABORTED; 162 } 163 auto status = brillo_audio_service_->SetVolumeControlStream( 164 BrilloAudioClientHelpers::GetStreamType(usage)); 165 return status.serviceSpecificErrorCode(); 166} 167 168int BrilloAudioClient::IncrementVolume() { 169 if (!brillo_audio_service_.get()) { 170 OnBASDisconnect(); 171 return ECONNABORTED; 172 } 173 auto status = brillo_audio_service_->IncrementVolume(); 174 return status.serviceSpecificErrorCode(); 175} 176 177int BrilloAudioClient::DecrementVolume() { 178 if (!brillo_audio_service_.get()) { 179 OnBASDisconnect(); 180 return ECONNABORTED; 181 } 182 auto status = brillo_audio_service_->DecrementVolume(); 183 return status.serviceSpecificErrorCode(); 184} 185 186int BrilloAudioClient::RegisterAudioCallback( 187 android::sp<AudioServiceCallback> callback, int* callback_id) { 188 if (!brillo_audio_service_.get()) { 189 OnBASDisconnect(); 190 return ECONNABORTED; 191 } 192 if (!brillo_audio_service_->RegisterServiceCallback(callback).isOk()) { 193 *callback_id = 0; 194 return ECONNABORTED; 195 } 196 for (auto& entry : callback_map_) { 197 if (entry.second->Equals(callback)) { 198 LOG(ERROR) << "Callback has already been registered."; 199 *callback_id = 0; 200 return EINVAL; 201 } 202 } 203 *callback_id = callback_id_counter_++; 204 callback_map_.emplace(*callback_id, callback); 205 return 0; 206} 207 208int BrilloAudioClient::UnregisterAudioCallback(int callback_id) { 209 if (!brillo_audio_service_.get()) { 210 OnBASDisconnect(); 211 return ECONNABORTED; 212 } 213 auto callback_elem = callback_map_.find(callback_id); 214 if (callback_elem == callback_map_.end()) { 215 // If we were passed an invalid callback_id, do nothing. 216 LOG(ERROR) << "Unregister called with invalid callback ID."; 217 return EINVAL; 218 } 219 brillo_audio_service_->UnregisterServiceCallback(callback_elem->second.get()); 220 callback_map_.erase(callback_elem); 221 return 0; 222} 223 224} // namespace brillo 225