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_manager.h.
17
18#include "include/brillo_audio_manager.h"
19
20#include <memory>
21#include <stdlib.h>
22
23#include "audio_service_callback.h"
24#include "brillo_audio_client.h"
25#include "brillo_audio_client_helpers.h"
26#include "brillo_audio_device_info_def.h"
27#include "brillo_audio_device_info_internal.h"
28
29using brillo::AudioServiceCallback;
30using brillo::BrilloAudioClient;
31using brillo::BrilloAudioClientHelpers;
32
33struct BAudioManager {
34  std::weak_ptr<BrilloAudioClient> client_;
35};
36
37BAudioManager* BAudioManager_new() {
38  auto client = BrilloAudioClient::GetClientInstance();
39  if (!client.lock())
40    return nullptr;
41  BAudioManager* bam = new BAudioManager;
42  bam->client_ = client;
43  return bam;
44}
45
46int BAudioManager_getDevices(
47    const BAudioManager* brillo_audio_manager, int flag,
48    BAudioDeviceInfo* device_array[], unsigned int size,
49    unsigned int* num_devices) {
50  if (!brillo_audio_manager || !num_devices ||
51      (flag != GET_DEVICES_INPUTS && flag != GET_DEVICES_OUTPUTS))
52    return EINVAL;
53  auto client = brillo_audio_manager->client_.lock();
54  if (!client) {
55    *num_devices = 0;
56    return ECONNABORTED;
57  }
58  std::vector<int> devices;
59  auto rc = client->GetDevices(flag, devices);
60  if (rc) {
61    *num_devices = 0;
62    return rc;
63  }
64  unsigned int num_elems = (devices.size() < size) ? devices.size() : size;
65  for (size_t i = 0; i < num_elems; i++) {
66    device_array[i] = new BAudioDeviceInfo;
67    device_array[i]->internal_ = std::unique_ptr<BAudioDeviceInfoInternal>(
68        BAudioDeviceInfoInternal::CreateFromAudioDevicesT(devices[i]));
69  }
70  *num_devices = devices.size();
71  return 0;
72}
73
74int BAudioManager_setInputDevice(const BAudioManager* brillo_audio_manager,
75                                 const BAudioDeviceInfo* device) {
76  if (!brillo_audio_manager || !device)
77    return EINVAL;
78  auto client = brillo_audio_manager->client_.lock();
79  if (!client) {
80    return ECONNABORTED;
81  }
82  return client->SetDevice(AUDIO_POLICY_FORCE_FOR_RECORD,
83                           device->internal_->GetConfig());
84}
85
86int BAudioManager_setOutputDevice(
87    const BAudioManager* brillo_audio_manager, const BAudioDeviceInfo* device,
88    BAudioUsage usage) {
89  if (!brillo_audio_manager || !device)
90    return EINVAL;
91  auto client = brillo_audio_manager->client_.lock();
92  if (!client)
93    return ECONNABORTED;
94  return client->SetDevice(BrilloAudioClientHelpers::GetForceUse(usage),
95                           device->internal_->GetConfig());
96}
97
98int BAudioManager_getMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
99                                    BAudioUsage usage,
100                                    int* max_steps) {
101  if (!brillo_audio_manager || !max_steps)
102    return EINVAL;
103  auto client = brillo_audio_manager->client_.lock();
104  if (!client)
105    return ECONNABORTED;
106  return client->GetMaxVolumeSteps(usage, max_steps);
107}
108
109int BAudioManager_setMaxVolumeSteps(const BAudioManager* brillo_audio_manager,
110                                    BAudioUsage usage,
111                                    int max_steps) {
112  if (!brillo_audio_manager || max_steps < 0 || max_steps > 100)
113    return EINVAL;
114  auto client = brillo_audio_manager->client_.lock();
115  if (!client)
116    return ECONNABORTED;
117  return client->SetMaxVolumeSteps(usage, max_steps);
118}
119
120int BAudioManager_setVolumeIndex(const BAudioManager* brillo_audio_manager,
121                                 BAudioUsage usage,
122                                 const BAudioDeviceInfo* device,
123                                 int index) {
124  if (!brillo_audio_manager || !device) {
125    return EINVAL;
126  }
127  auto client = brillo_audio_manager->client_.lock();
128  if (!client) {
129    return ECONNABORTED;
130  }
131  return client->SetVolumeIndex(
132      usage, device->internal_->GetAudioDevicesT(), index);
133}
134
135int BAudioManager_getVolumeIndex(const BAudioManager* brillo_audio_manager,
136                                 BAudioUsage usage,
137                                 const BAudioDeviceInfo* device,
138                                 int* index) {
139  if (!brillo_audio_manager || !device || !index) {
140    return EINVAL;
141  }
142  auto client = brillo_audio_manager->client_.lock();
143  if (!client) {
144    return ECONNABORTED;
145  }
146  return client->GetVolumeIndex(
147      usage, device->internal_->GetAudioDevicesT(), index);
148}
149
150int BAudioManager_getVolumeControlUsage(
151    const BAudioManager* brillo_audio_manager, BAudioUsage* usage) {
152  if (!brillo_audio_manager || !usage) {
153    return EINVAL;
154  }
155  auto client = brillo_audio_manager->client_.lock();
156  if (!client) {
157    return ECONNABORTED;
158  }
159  return client->GetVolumeControlStream(usage);
160}
161
162int BAudioManager_setVolumeControlUsage(
163    const BAudioManager* brillo_audio_manager, BAudioUsage usage) {
164  if (!brillo_audio_manager) {
165    return EINVAL;
166  }
167  auto client = brillo_audio_manager->client_.lock();
168  if (!client) {
169    return ECONNABORTED;
170  }
171  return client->SetVolumeControlStream(usage);
172}
173
174int BAudioManager_incrementVolume(const BAudioManager* brillo_audio_manager) {
175  if (!brillo_audio_manager) {
176    return EINVAL;
177  }
178  auto client = brillo_audio_manager->client_.lock();
179  if (!client) {
180    return ECONNABORTED;
181  }
182  return client->IncrementVolume();
183}
184
185int BAudioManager_decrementVolume(const BAudioManager* brillo_audio_manager) {
186  if (!brillo_audio_manager) {
187    return EINVAL;
188  }
189  auto client = brillo_audio_manager->client_.lock();
190  if (!client) {
191    return ECONNABORTED;
192  }
193  return client->DecrementVolume();
194}
195
196int BAudioManager_registerAudioCallback(
197    const BAudioManager* brillo_audio_manager, const BAudioCallback* callback,
198    void* user_data, int* callback_id) {
199  if (!brillo_audio_manager || !callback || !callback_id)
200    return EINVAL;
201  auto client = brillo_audio_manager->client_.lock();
202  if (!client) {
203    *callback_id = 0;
204    return ECONNABORTED;
205  }
206  // This copies the BAudioCallback into AudioServiceCallback so the
207  // BAudioCallback can be safely deleted.
208  return client->RegisterAudioCallback(
209      new AudioServiceCallback(callback, user_data), callback_id);
210}
211
212int BAudioManager_unregisterAudioCallback(
213    const BAudioManager* brillo_audio_manager, int callback_id) {
214  if (!brillo_audio_manager)
215    return EINVAL;
216  auto client = brillo_audio_manager->client_.lock();
217  if (!client)
218    return ECONNABORTED;
219  return client->UnregisterAudioCallback(callback_id);
220}
221
222int BAudioManager_delete(BAudioManager* brillo_audio_manager) {
223  if (!brillo_audio_manager)
224    return EINVAL;
225  delete brillo_audio_manager;
226  return 0;
227}
228