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
28 using android::binder::Status;
29
30 namespace brillo {
31
32 static const char kBrilloAudioServiceName[] =
33 "android.brillo.brilloaudioservice.BrilloAudioService";
34
35 std::shared_ptr<BrilloAudioClient> BrilloAudioClient::instance_ = nullptr;
36
37 int BrilloAudioClient::callback_id_counter_ = 1;
38
~BrilloAudioClient()39 BrilloAudioClient::~BrilloAudioClient() {}
40
GetClientInstance()41 std::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
ConnectToService(const std::string & service_name,const base::Closure & callback)53 android::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
OnBASDisconnect()65 void BrilloAudioClient::OnBASDisconnect() {
66 LOG(WARNING) << "The brillo audio service died! Please reset the "
67 << "BAudioManager.";
68 instance_.reset();
69 }
70
Initialize()71 bool 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
GetDevices(int flag,std::vector<int> & devices)83 int 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
SetDevice(audio_policy_force_use_t usage,audio_policy_forced_cfg_t config)92 int 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
GetMaxVolumeSteps(BAudioUsage usage,int * max_steps)102 int 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
SetMaxVolumeSteps(BAudioUsage usage,int max_steps)112 int 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
SetVolumeIndex(BAudioUsage usage,audio_devices_t device,int index)122 int 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
GetVolumeIndex(BAudioUsage usage,audio_devices_t device,int * index)134 int 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
GetVolumeControlStream(BAudioUsage * usage)146 int 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
SetVolumeControlStream(BAudioUsage usage)158 int 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
IncrementVolume()168 int 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
DecrementVolume()177 int 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
RegisterAudioCallback(android::sp<AudioServiceCallback> callback,int * callback_id)186 int 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
UnregisterAudioCallback(int callback_id)208 int 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