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