1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <log/log.h>
18 #include <system/audio.h>
19 #include "primary_device.h"
20 #include "stream_in.h"
21 #include "stream_out.h"
22 #include "util.h"
23 #include "debug.h"
24
25 namespace android {
26 namespace hardware {
27 namespace audio {
28 namespace V6_0 {
29 namespace implementation {
30
31 constexpr size_t kInBufferDurationMs = 15;
32 constexpr size_t kOutBufferDurationMs = 22;
33
34 using ::android::hardware::Void;
35
PrimaryDevice()36 PrimaryDevice::PrimaryDevice()
37 : mMixer(talsa::mixerOpen(talsa::kPcmDevice)) {
38 if (mMixer) {
39 mMixerMasterVolumeCtl = mixer_get_ctl_by_name(mMixer.get(), "Master Playback Volume");
40 mMixerCaptureVolumeCtl = mixer_get_ctl_by_name(mMixer.get(), "Capture Volume");
41 mMixerMasterPaybackSwitchCtl = mixer_get_ctl_by_name(mMixer.get(), "Master Playback Switch");
42 mMixerCaptureSwitchCtl = mixer_get_ctl_by_name(mMixer.get(), "Capture Switch");
43
44 talsa::mixerSetPercentAll(mMixerMasterVolumeCtl, 100);
45 talsa::mixerSetPercentAll(mMixerCaptureVolumeCtl, 100);
46 talsa::mixerSetValueAll(mMixerMasterPaybackSwitchCtl, 1);
47 talsa::mixerSetValueAll(mMixerCaptureSwitchCtl, 1);
48 }
49 }
50
initCheck()51 Return<Result> PrimaryDevice::initCheck() {
52 return mMixer ? Result::OK : FAILURE(Result::NOT_INITIALIZED);
53 }
54
setMasterVolume(float volume)55 Return<Result> PrimaryDevice::setMasterVolume(float volume) {
56 if (isnan(volume) || volume < 0 || volume > 1.0) {
57 return FAILURE(Result::INVALID_ARGUMENTS);
58 }
59
60 if (!mMixerMasterVolumeCtl) {
61 return FAILURE(Result::INVALID_STATE);
62 }
63
64 talsa::mixerSetPercentAll(mMixerMasterVolumeCtl, int(100 * volume));
65 mMasterVolume = volume;
66 return Result::OK;
67 }
68
getMasterVolume(getMasterVolume_cb _hidl_cb)69 Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
70 if (mMixerMasterVolumeCtl) {
71 _hidl_cb(Result::OK, mMasterVolume);
72 } else {
73 _hidl_cb(FAILURE(Result::INVALID_STATE), 0);
74 }
75
76 return Void();
77 }
78
setMicMute(bool mute)79 Return<Result> PrimaryDevice::PrimaryDevice::setMicMute(bool mute) {
80 if (mMixerCaptureSwitchCtl) {
81 talsa::mixerSetValueAll(mMixerCaptureSwitchCtl, mute ? 0 : 1);
82 return Result::OK;
83 } else {
84 return FAILURE(Result::INVALID_STATE);
85 }
86 }
87
getMicMute(getMicMute_cb _hidl_cb)88 Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
89 if (mMixerCaptureSwitchCtl) {
90 const int value = mixer_ctl_get_value(mMixerCaptureSwitchCtl, 0);
91 _hidl_cb(Result::OK, value == 0);
92 } else {
93 _hidl_cb(FAILURE(Result::INVALID_STATE), 0);
94 }
95 return Void();
96 }
97
setMasterMute(bool mute)98 Return<Result> PrimaryDevice::setMasterMute(bool mute) {
99 if (mMixerMasterPaybackSwitchCtl) {
100 talsa::mixerSetValueAll(mMixerMasterPaybackSwitchCtl, mute ? 0 : 1);
101 return Result::OK;
102 } else {
103 return FAILURE(Result::INVALID_STATE);
104 }
105 }
106
getMasterMute(getMasterMute_cb _hidl_cb)107 Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
108 if (mMixerMasterPaybackSwitchCtl) {
109 const int value = mixer_ctl_get_value(mMixerMasterPaybackSwitchCtl, 0);
110 _hidl_cb(Result::OK, value == 0);
111 } else {
112 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
113 }
114
115 return Void();
116 }
117
getInputBufferSize(const AudioConfig & config,getInputBufferSize_cb _hidl_cb)118 Return<void> PrimaryDevice::getInputBufferSize(const AudioConfig& config,
119 getInputBufferSize_cb _hidl_cb) {
120 AudioConfig suggestedConfig;
121 if (util::checkAudioConfig(false, kInBufferDurationMs, config, suggestedConfig)) {
122 const size_t sz =
123 suggestedConfig.frameCount
124 * util::countChannels(suggestedConfig.channelMask)
125 * util::getBytesPerSample(suggestedConfig.format);
126
127 _hidl_cb(Result::OK, sz);
128 } else {
129 ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
130 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), 0);
131 }
132
133 return Void();
134 }
135
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,hidl_bitfield<AudioOutputFlag> flags,const SourceMetadata & sourceMetadata,openOutputStream_cb _hidl_cb)136 Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle,
137 const DeviceAddress& device,
138 const AudioConfig& config,
139 hidl_bitfield<AudioOutputFlag> flags,
140 const SourceMetadata& sourceMetadata,
141 openOutputStream_cb _hidl_cb) {
142 AudioConfig suggestedConfig;
143 if (util::checkAudioConfig(true, kOutBufferDurationMs, config, suggestedConfig)) {
144 ++mNStreams;
145 _hidl_cb(Result::OK,
146 new StreamOut(this, &unrefDevice,
147 ioHandle, device, suggestedConfig, flags, sourceMetadata),
148 config);
149 } else {
150 ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
151 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), nullptr, suggestedConfig);
152 }
153
154 return Void();
155 }
156
openInputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,hidl_bitfield<AudioInputFlag> flags,const SinkMetadata & sinkMetadata,openInputStream_cb _hidl_cb)157 Return<void> PrimaryDevice::openInputStream(int32_t ioHandle,
158 const DeviceAddress& device,
159 const AudioConfig& config,
160 hidl_bitfield<AudioInputFlag> flags,
161 const SinkMetadata& sinkMetadata,
162 openInputStream_cb _hidl_cb) {
163 AudioConfig suggestedConfig;
164 if (util::checkAudioConfig(false, kInBufferDurationMs, config, suggestedConfig)) {
165 ++mNStreams;
166 _hidl_cb(Result::OK,
167 new StreamIn(this, &unrefDevice,
168 ioHandle, device, suggestedConfig, flags, sinkMetadata),
169 config);
170 } else {
171 ALOGE("PrimaryDevice::%s:%d failed", __func__, __LINE__);
172 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), nullptr, suggestedConfig);
173 }
174
175 return Void();
176 }
177
supportsAudioPatches()178 Return<bool> PrimaryDevice::supportsAudioPatches() {
179 return true;
180 }
181
createAudioPatch(const hidl_vec<AudioPortConfig> & sources,const hidl_vec<AudioPortConfig> & sinks,createAudioPatch_cb _hidl_cb)182 Return<void> PrimaryDevice::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
183 const hidl_vec<AudioPortConfig>& sinks,
184 createAudioPatch_cb _hidl_cb) {
185 if (sources.size() == 1 && sinks.size() == 1) {
186 AudioPatch patch;
187 patch.source = sources[0];
188 patch.sink = sinks[0];
189
190 AudioPatchHandle handle;
191 while (true) {
192 handle = mNextAudioPatchHandle;
193 mNextAudioPatchHandle = std::max(handle + 1, 0);
194 if (mAudioPatches.insert({handle, patch}).second) {
195 break;
196 }
197 }
198
199 _hidl_cb(Result::OK, handle);
200 } else {
201 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0);
202 }
203
204 return Void();
205 }
206
updateAudioPatch(AudioPatchHandle previousPatchHandle,const hidl_vec<AudioPortConfig> & sources,const hidl_vec<AudioPortConfig> & sinks,updateAudioPatch_cb _hidl_cb)207 Return<void> PrimaryDevice::updateAudioPatch(AudioPatchHandle previousPatchHandle,
208 const hidl_vec<AudioPortConfig>& sources,
209 const hidl_vec<AudioPortConfig>& sinks,
210 updateAudioPatch_cb _hidl_cb) {
211 const auto i = mAudioPatches.find(previousPatchHandle);
212 if (i == mAudioPatches.end()) {
213 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), previousPatchHandle);
214 } else {
215 if (sources.size() == 1 && sinks.size() == 1) {
216 AudioPatch patch;
217 patch.source = sources[0];
218 patch.sink = sinks[0];
219 i->second = patch;
220
221 _hidl_cb(Result::OK, previousPatchHandle);
222 } else {
223 _hidl_cb(Result::NOT_SUPPORTED, previousPatchHandle);
224 }
225 }
226
227 return Void();
228 }
229
releaseAudioPatch(AudioPatchHandle patchHandle)230 Return<Result> PrimaryDevice::releaseAudioPatch(AudioPatchHandle patchHandle) {
231 return (mAudioPatches.erase(patchHandle) == 1) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
232 }
233
getAudioPort(const AudioPort & port,getAudioPort_cb _hidl_cb)234 Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
235 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), port);
236 return Void();
237 }
238
setAudioPortConfig(const AudioPortConfig & config)239 Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
240 (void)config;
241 return FAILURE(Result::NOT_SUPPORTED);
242 }
243
setScreenState(bool turnedOn)244 Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
245 (void)turnedOn;
246 return Result::OK;
247 }
248
getHwAvSync(getHwAvSync_cb _hidl_cb)249 Return<void> PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) {
250 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
251 return Void();
252 }
253
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)254 Return<void> PrimaryDevice::getParameters(const hidl_vec<ParameterValue>& context,
255 const hidl_vec<hidl_string>& keys,
256 getParameters_cb _hidl_cb) {
257 (void)context;
258 if (keys.size() == 0) {
259 _hidl_cb(Result::OK, {});
260 } else {
261 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
262 }
263 return Void();
264 }
265
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)266 Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& context,
267 const hidl_vec<ParameterValue>& parameters) {
268 (void)context;
269 (void)parameters;
270 return Result::OK;
271 }
272
getMicrophones(getMicrophones_cb _hidl_cb)273 Return<void> PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) {
274 _hidl_cb(Result::OK, {util::getMicrophoneInfo()});
275 return Void();
276 }
277
setConnectedState(const DeviceAddress & dev_addr,bool connected)278 Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& dev_addr, bool connected) {
279 (void)dev_addr;
280 (void)connected;
281 return FAILURE(Result::NOT_SUPPORTED);
282 }
283
close()284 Return<Result> PrimaryDevice::close() {
285 if (mNStreams > 0) {
286 return FAILURE(Result::INVALID_STATE);
287 } else if (mMixer) {
288 mMixerMasterVolumeCtl = nullptr;
289 mMixerCaptureVolumeCtl = nullptr;
290 mMixerMasterPaybackSwitchCtl = nullptr;
291 mMixerCaptureSwitchCtl = nullptr;
292 mMixer.reset();
293 return Result::OK;
294 } else {
295 return FAILURE(Result::INVALID_STATE);
296 }
297 }
298
addDeviceEffect(AudioPortHandle device,uint64_t effectId)299 Return<Result> PrimaryDevice::addDeviceEffect(AudioPortHandle device, uint64_t effectId) {
300 (void)device;
301 (void)effectId;
302 return FAILURE(Result::NOT_SUPPORTED);
303 }
304
removeDeviceEffect(AudioPortHandle device,uint64_t effectId)305 Return<Result> PrimaryDevice::removeDeviceEffect(AudioPortHandle device, uint64_t effectId) {
306 (void)device;
307 (void)effectId;
308 return FAILURE(Result::NOT_SUPPORTED);
309 }
310
setVoiceVolume(float volume)311 Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
312 return (volume >= 0 && volume <= 1.0) ? Result::OK : FAILURE(Result::INVALID_ARGUMENTS);
313 }
314
setMode(AudioMode mode)315 Return<Result> PrimaryDevice::setMode(AudioMode mode) {
316 switch (mode) {
317 case AudioMode::NORMAL:
318 case AudioMode::RINGTONE:
319 case AudioMode::IN_CALL:
320 case AudioMode::IN_COMMUNICATION:
321 return Result::OK;
322
323 default:
324 return FAILURE(Result::INVALID_ARGUMENTS);
325 }
326 }
327
setBtScoHeadsetDebugName(const hidl_string & name)328 Return<Result> PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) {
329 (void)name;
330 return FAILURE(Result::NOT_SUPPORTED);
331 }
332
getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb)333 Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
334 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
335 return Void();
336 }
337
setBtScoNrecEnabled(bool enabled)338 Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
339 (void)enabled;
340 return FAILURE(Result::NOT_SUPPORTED);
341 }
342
getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb)343 Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) {
344 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
345 return Void();
346 }
347
setBtScoWidebandEnabled(bool enabled)348 Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
349 (void)enabled;
350 return FAILURE(Result::NOT_SUPPORTED);
351 }
352
getTtyMode(getTtyMode_cb _hidl_cb)353 Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
354 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), TtyMode::OFF);
355 return Void();
356 }
357
setTtyMode(IPrimaryDevice::TtyMode mode)358 Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
359 (void)mode;
360 return FAILURE(Result::NOT_SUPPORTED);
361 }
362
getHacEnabled(getHacEnabled_cb _hidl_cb)363 Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
364 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
365 return Void();
366 }
367
setHacEnabled(bool enabled)368 Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
369 (void)enabled;
370 return FAILURE(Result::NOT_SUPPORTED);
371 }
372
getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb)373 Return<void> PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) {
374 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), false);
375 return Void();
376 }
377
setBtHfpEnabled(bool enabled)378 Return<Result> PrimaryDevice::setBtHfpEnabled(bool enabled) {
379 (void)enabled;
380 return FAILURE(Result::NOT_SUPPORTED);
381 }
382
setBtHfpSampleRate(uint32_t sampleRateHz)383 Return<Result> PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) {
384 (void)sampleRateHz;
385 return FAILURE(Result::NOT_SUPPORTED);
386 }
387
setBtHfpVolume(float volume)388 Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
389 (void)volume;
390 return FAILURE(Result::NOT_SUPPORTED);
391 }
392
updateRotation(IPrimaryDevice::Rotation rotation)393 Return<Result> PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) {
394 (void)rotation;
395 return FAILURE(Result::NOT_SUPPORTED);
396 }
397
unrefDevice(IDevice * dev)398 void PrimaryDevice::unrefDevice(IDevice *dev) {
399 static_cast<PrimaryDevice *>(dev)->unrefDeviceImpl();
400 }
401
unrefDeviceImpl()402 void PrimaryDevice::unrefDeviceImpl() {
403 LOG_ALWAYS_FATAL_IF(--mNStreams < 0);
404 }
405
406 } // namespace implementation
407 } // namespace V6_0
408 } // namespace audio
409 } // namespace hardware
410 } // namespace android
411