blob: 5f62ad81dcd6175633342e084fc7efa5abf385e0 [file] [log] [blame]
Mikhail Naganov31d46652023-01-10 18:29:25 +00001/*
2 * Copyright (C) 2023 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#define LOG_TAG "StreamHalAidl"
18//#define LOG_NDEBUG 0
19
Mikhail Naganov89a9f742023-01-30 12:33:18 -080020#include <algorithm>
21#include <cstdint>
22
Mikhail Naganov89a9f742023-01-30 12:33:18 -080023#include <audio_utils/clock.h>
David Lia0ad9f02023-03-02 21:46:19 +080024#include <media/AidlConversionCppNdk.h>
Mikhail Naganovb6e57752023-03-08 18:12:47 -080025#include <media/AidlConversionNdk.h>
David Lia6fb5752023-02-23 15:32:47 +000026#include <media/AidlConversionUtil.h>
David Lia0ad9f02023-03-02 21:46:19 +080027#include <media/AudioParameter.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000028#include <mediautils/TimeCheck.h>
David Lia0ad9f02023-03-02 21:46:19 +080029#include <system/audio.h>
Mikhail Naganov31d46652023-01-10 18:29:25 +000030#include <utils/Log.h>
31
32#include "DeviceHalAidl.h"
33#include "StreamHalAidl.h"
34
David Lia6fb5752023-02-23 15:32:47 +000035using ::aidl::android::aidl_utils::statusTFromBinderStatus;
Mikhail Naganovb6e57752023-03-08 18:12:47 -080036using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata;
37using ::aidl::android::hardware::audio::common::RecordTrackMetadata;
Mikhail Naganov31d46652023-01-10 18:29:25 +000038using ::aidl::android::hardware::audio::core::IStreamCommon;
39using ::aidl::android::hardware::audio::core::IStreamIn;
40using ::aidl::android::hardware::audio::core::IStreamOut;
41using ::aidl::android::hardware::audio::core::StreamDescriptor;
David Lia0ad9f02023-03-02 21:46:19 +080042using ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout;
Mikhail Naganov31d46652023-01-10 18:29:25 +000043
44namespace android {
45
Mikhail Naganov89a9f742023-01-30 12:33:18 -080046using HalCommand = StreamDescriptor::Command;
47namespace {
48template<HalCommand::Tag cmd> HalCommand makeHalCommand() {
49 return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{});
50}
51template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
52 return HalCommand::make<cmd>(data);
53}
54} // namespace
55
Mikhail Naganovfab697c2023-01-11 19:33:13 +000056// static
57template<class T>
58std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
59 std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> streamCommon;
60 if (stream != nullptr) {
61 if (ndk::ScopedAStatus status = stream->getStreamCommon(&streamCommon);
62 !status.isOk()) {
63 ALOGE("%s: failed to retrieve IStreamCommon instance: %s", __func__,
64 status.getDescription().c_str());
65 }
66 }
67 return streamCommon;
68}
69
Mikhail Naganov31d46652023-01-10 18:29:25 +000070StreamHalAidl::StreamHalAidl(
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080071 std::string_view className, bool isInput, const audio_config& config,
Mikhail Naganov89a9f742023-01-30 12:33:18 -080072 int32_t nominalLatency, StreamContextAidl&& context,
73 const std::shared_ptr<IStreamCommon>& stream)
Mikhail Naganov31d46652023-01-10 18:29:25 +000074 : ConversionHelperAidl(className),
75 mIsInput(isInput),
Mikhail Naganov5b1eed12023-01-25 11:29:11 -080076 mConfig(configToBase(config)),
Mikhail Naganov89a9f742023-01-30 12:33:18 -080077 mContext(std::move(context)),
Mikhail Naganov31d46652023-01-10 18:29:25 +000078 mStream(stream) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -080079 {
80 std::lock_guard l(mLock);
81 mLastReply.latencyMs = nominalLatency;
82 }
Mikhail Naganov31d46652023-01-10 18:29:25 +000083 // Instrument audio signal power logging.
84 // Note: This assumes channel mask, format, and sample rate do not change after creation.
85 if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
86 /* mStreamPowerLog.isUserDebugOrEngBuild() && */
87 StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
88 mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
89 }
90}
91
92StreamHalAidl::~StreamHalAidl() {
93 if (mStream != nullptr) {
94 ndk::ScopedAStatus status = mStream->close();
95 ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
96 }
97}
98
99status_t StreamHalAidl::getBufferSize(size_t *size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800100 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000101 if (size == nullptr) {
102 return BAD_VALUE;
103 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800104 if (mContext.getFrameSizeBytes() == 0 || mContext.getBufferSizeFrames() == 0 ||
105 !mStream) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000106 return NO_INIT;
107 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800108 *size = mContext.getBufferSizeBytes();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000109 return OK;
110}
111
112status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800113 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000114 if (configBase == nullptr) {
115 return BAD_VALUE;
116 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800117 if (!mStream) return NO_INIT;
118 *configBase = mConfig;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000119 return OK;
120}
121
122status_t StreamHalAidl::setParameters(const String8& kvPairs __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800123 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000124 TIME_CHECK();
125 if (!mStream) return NO_INIT;
126 ALOGE("%s not implemented yet", __func__);
127 return OK;
128}
129
130status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800131 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000132 TIME_CHECK();
133 values->clear();
134 if (!mStream) return NO_INIT;
135 ALOGE("%s not implemented yet", __func__);
136 return OK;
137}
138
139status_t StreamHalAidl::getFrameSize(size_t *size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800140 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000141 if (size == nullptr) {
142 return BAD_VALUE;
143 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800144 if (mContext.getFrameSizeBytes() == 0 || !mStream) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000145 return NO_INIT;
146 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800147 *size = mContext.getFrameSizeBytes();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000148 return OK;
149}
150
151status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800152 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000153 TIME_CHECK();
154 if (!mStream) return NO_INIT;
155 ALOGE("%s not implemented yet", __func__);
156 return OK;
157}
158
159status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800160 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000161 TIME_CHECK();
162 if (!mStream) return NO_INIT;
163 ALOGE("%s not implemented yet", __func__);
164 return OK;
165}
166
167status_t StreamHalAidl::standby() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800168 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000169 TIME_CHECK();
170 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800171 const auto state = getState();
172 StreamDescriptor::Reply reply;
173 switch (state) {
174 case StreamDescriptor::State::ACTIVE:
175 if (status_t status = pause(&reply); status != OK) return status;
176 if (reply.state != StreamDescriptor::State::PAUSED) {
177 ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
178 __func__, toString(reply.state).c_str());
179 return INVALID_OPERATION;
180 }
181 FALLTHROUGH_INTENDED;
182 case StreamDescriptor::State::PAUSED:
183 case StreamDescriptor::State::DRAIN_PAUSED:
Jasmine Cha105c66f2023-02-15 16:29:36 +0800184 if (mIsInput) return flush();
185 if (status_t status = flush(&reply); status != OK) return status;
186 if (reply.state != StreamDescriptor::State::IDLE) {
187 ALOGE("%s: unexpected stream state: %s (expected IDLE)",
188 __func__, toString(reply.state).c_str());
189 return INVALID_OPERATION;
190 }
191 FALLTHROUGH_INTENDED;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800192 case StreamDescriptor::State::IDLE:
193 if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
Jasmine Cha105c66f2023-02-15 16:29:36 +0800194 &reply, true /*safeFromNonWorkerThread*/); status != OK) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800195 return status;
196 }
197 if (reply.state != StreamDescriptor::State::STANDBY) {
198 ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
199 __func__, toString(reply.state).c_str());
200 return INVALID_OPERATION;
201 }
202 FALLTHROUGH_INTENDED;
203 case StreamDescriptor::State::STANDBY:
204 return OK;
205 default:
206 ALOGE("%s: not supported from %s stream state %s",
207 __func__, mIsInput ? "input" : "output", toString(state).c_str());
208 return INVALID_OPERATION;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800209 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000210}
211
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000212status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800213 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000214 TIME_CHECK();
215 if (!mStream) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000216 return mStream->dump(fd, Args(args).args(), args.size());
Mikhail Naganov31d46652023-01-10 18:29:25 +0000217}
218
219status_t StreamHalAidl::start() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800220 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000221 TIME_CHECK();
222 if (!mStream) return NO_INIT;
223 ALOGE("%s not implemented yet", __func__);
224 return OK;
225}
226
227status_t StreamHalAidl::stop() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800228 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
229 TIME_CHECK();
230 if (!mStream) return NO_INIT;
231 ALOGE("%s not implemented yet", __func__);
232 return OK;
233}
234
235status_t StreamHalAidl::getLatency(uint32_t *latency) {
236 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
237 if (!mStream) return NO_INIT;
238 StreamDescriptor::Reply reply;
239 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
240 return status;
241 }
242 *latency = std::max<int32_t>(0, reply.latencyMs);
243 return OK;
244}
245
246status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) {
247 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
248 if (!mStream) return NO_INIT;
249 StreamDescriptor::Reply reply;
250 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
251 return status;
252 }
253 *frames = reply.observable.frames;
254 *timestamp = reply.observable.timeNs;
255 return OK;
256}
257
258status_t StreamHalAidl::getXruns(int32_t *frames) {
259 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
260 if (!mStream) return NO_INIT;
261 StreamDescriptor::Reply reply;
262 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
263 return status;
264 }
265 *frames = reply.xrunFrames;
266 return OK;
267}
268
269status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
270 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
Shunkai Yaoc6308712023-02-22 17:53:04 +0000271 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800272 if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
273 mWorkerTid.store(gettid(), std::memory_order_release);
274 // Switch the stream into an active state if needed.
275 // Note: in future we may add support for priming the audio pipeline
276 // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
277 // stream state), however this scenario wasn't supported by the HIDL HAL.
278 if (getState() == StreamDescriptor::State::STANDBY) {
279 StreamDescriptor::Reply reply;
280 if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
281 status != OK) {
282 return status;
283 }
284 if (reply.state != StreamDescriptor::State::IDLE) {
285 ALOGE("%s: failed to get the stream out of standby, actual state: %s",
286 __func__, toString(reply.state).c_str());
287 return INVALID_OPERATION;
288 }
289 }
290 if (!mIsInput) {
291 bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite());
292 }
293 StreamDescriptor::Command burst =
294 StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
295 if (!mIsInput) {
296 if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
297 ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
298 return NOT_ENOUGH_DATA;
299 }
300 }
301 StreamDescriptor::Reply reply;
302 if (status_t status = sendCommand(burst, &reply); status != OK) {
303 return status;
304 }
Jasmine Chaad99fb02023-02-10 12:52:58 +0800305 *transferred = reply.fmqByteCount;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800306 if (mIsInput) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800307 LOG_ALWAYS_FATAL_IF(*transferred > bytes,
308 "%s: HAL module read %zu bytes, which exceeds requested count %zu",
309 __func__, *transferred, bytes);
Jasmine Cha105c66f2023-02-15 16:29:36 +0800310 if (auto toRead = mContext.getDataMQ()->availableToRead();
311 toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
312 ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800313 return NOT_ENOUGH_DATA;
314 }
315 }
316 mStreamPowerLog.log(buffer, *transferred);
317 return OK;
318}
319
320status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
321 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
322 TIME_CHECK();
323 if (!mStream) return NO_INIT;
324 return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
325 true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
326}
327
328status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
329 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
330 TIME_CHECK();
331 if (!mStream) return NO_INIT;
332 if (mIsInput) {
333 return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
334 } else {
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800335 if (mContext.isAsynchronous()) {
336 // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
337 // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
338 const auto state = getState();
339 if (state == StreamDescriptor::State::IDLE) {
340 StreamDescriptor::Reply localReply{};
341 StreamDescriptor::Reply* innerReply = reply ?: &localReply;
342 if (status_t status =
343 sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
344 status != OK) {
345 return status;
346 }
347 if (innerReply->state != StreamDescriptor::State::ACTIVE) {
348 ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
349 __func__, toString(innerReply->state).c_str());
350 return INVALID_OPERATION;
351 }
352 return OK;
353 }
354 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800355 return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
356 }
357}
358
359status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
360 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
361 TIME_CHECK();
362 if (!mStream) return NO_INIT;
363 return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
364 mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
365 earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
David Lia6fb5752023-02-23 15:32:47 +0000366 StreamDescriptor::DrainMode::DRAIN_ALL), reply,
367 true /*safeFromNonWorkerThread*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800368}
369
370status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
371 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
372 TIME_CHECK();
373 if (!mStream) return NO_INIT;
374 return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
375 true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
376}
377
378status_t StreamHalAidl::exit() {
379 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000380 TIME_CHECK();
381 if (!mStream) return NO_INIT;
382 ALOGE("%s not implemented yet", __func__);
383 return OK;
384}
385
386status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
387 struct audio_mmap_buffer_info *info __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800388 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000389 TIME_CHECK();
390 if (!mStream) return NO_INIT;
391 ALOGE("%s not implemented yet", __func__);
392 return OK;
393}
394
395status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800396 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000397 TIME_CHECK();
398 if (!mStream) return NO_INIT;
399 ALOGE("%s not implemented yet", __func__);
400 return OK;
401}
402
403status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800404 // Obsolete, must be done by the HAL module.
Mikhail Naganov31d46652023-01-10 18:29:25 +0000405 return OK;
406}
407
408status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800409 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000410 TIME_CHECK();
411 if (!mStream) return NO_INIT;
412 ALOGE("%s not implemented yet", __func__);
413 return OK;
414}
415
416bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800417 // Obsolete, must be done by the HAL module.
418 return true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000419}
420
421status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
422 std::optional<audio_source_t> source __unused,
423 audio_devices_t type __unused) {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000424 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
425 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000426}
427
428status_t StreamHalAidl::legacyReleaseAudioPatch() {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000429 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
430 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000431}
432
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800433status_t StreamHalAidl::sendCommand(
434 const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
435 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
436 bool safeFromNonWorkerThread) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000437 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800438 if (!safeFromNonWorkerThread) {
439 const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
440 LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
441 "%s %s: must be invoked from the worker thread (%d)",
442 __func__, command.toString().c_str(), workerTid);
443 }
444 if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
445 ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
446 return NOT_ENOUGH_DATA;
447 }
448 StreamDescriptor::Reply localReply{};
449 if (reply == nullptr) {
450 reply = &localReply;
451 }
452 if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
453 ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str());
454 return NOT_ENOUGH_DATA;
455 }
456 {
457 std::lock_guard l(mLock);
458 mLastReply = *reply;
459 }
460 switch (reply->status) {
461 case STATUS_OK: return OK;
462 case STATUS_BAD_VALUE: return BAD_VALUE;
463 case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
464 case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
465 default:
466 ALOGE("%s: unexpected status %d returned for command %s",
467 __func__, reply->status, command.toString().c_str());
468 return INVALID_OPERATION;
469 }
470}
471
472status_t StreamHalAidl::updateCountersIfNeeded(
473 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
474 if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
475 if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
476 state != StreamDescriptor::State::DRAINING &&
477 state != StreamDescriptor::State::TRANSFERRING) {
478 return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
479 }
480 }
481 if (reply != nullptr) {
482 std::lock_guard l(mLock);
483 *reply = mLastReply;
484 }
485 return OK;
486}
487
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800488// static
Mikhail Naganov19418e32023-03-10 17:55:14 -0800489ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800490StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
491 ::aidl::android::hardware::audio::common::SourceMetadata aidl;
492 aidl.tracks = VALUE_OR_RETURN(
493 ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
494 legacy.tracks,
495 ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
496 return aidl;
497}
498
Mikhail Naganov31d46652023-01-10 18:29:25 +0000499StreamOutHalAidl::StreamOutHalAidl(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800500 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800501 const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800502 : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
503 std::move(context), getStreamCommon(stream)),
David Lia0ad9f02023-03-02 21:46:19 +0800504 mStream(stream), mCallbackBroker(callbackBroker) {
505 // Initialize the offload metadata
506 mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
507 mOffloadMetadata.channelMask = VALUE_OR_FATAL(
Mikhail Naganov893b7c22023-03-13 15:48:11 -0700508 ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
509 config.channel_mask, false));
David Lia0ad9f02023-03-02 21:46:19 +0800510 mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
511}
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800512
513StreamOutHalAidl::~StreamOutHalAidl() {
514 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
515 broker->clearCallbacks(this);
516 }
517}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000518
David Lia0ad9f02023-03-02 21:46:19 +0800519status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
520 if (!mStream) return NO_INIT;
521
522 AudioParameter parameters(kvPairs);
523 ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
524
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800525 if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
526 ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
David Lia0ad9f02023-03-02 21:46:19 +0800527 }
528
529 return StreamHalAidl::setParameters(parameters.toString());
530}
531
Mikhail Naganov31d46652023-01-10 18:29:25 +0000532status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800533 return StreamHalAidl::getLatency(latency);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000534}
535
David Lia6fb5752023-02-23 15:32:47 +0000536status_t StreamOutHalAidl::setVolume(float left, float right) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000537 TIME_CHECK();
538 if (!mStream) return NO_INIT;
David Lia6fb5752023-02-23 15:32:47 +0000539 return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000540}
541
542status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
543 TIME_CHECK();
544 if (!mStream) return NO_INIT;
545 ALOGE("%s not implemented yet", __func__);
546 return OK;
547}
548
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800549status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
550 if (buffer == nullptr || written == nullptr) {
551 return BAD_VALUE;
552 }
553 // For the output scenario, 'transfer' does not modify the buffer.
554 return transfer(const_cast<void*>(buffer), bytes, written);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000555}
556
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800557status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
558 if (dspFrames == nullptr) {
559 return BAD_VALUE;
560 }
561 int64_t aidlFrames = 0, aidlTimestamp = 0;
562 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
563 return OK;
564 }
565 *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000566 return OK;
567}
568
569status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800570 // Obsolete, use getPresentationPosition.
571 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000572}
573
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800574status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000575 TIME_CHECK();
576 if (!mStream) return NO_INIT;
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800577 if (!mContext.isAsynchronous()) {
578 ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
579 return INVALID_OPERATION;
580 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800581 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
582 if (auto cb = callback.promote(); cb != nullptr) {
583 broker->setStreamOutCallback(this, cb);
584 } else {
585 // It is expected that the framework never passes a null pointer.
586 // In the AIDL model callbacks can't be "unregistered".
587 LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
588 }
589 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000590 return OK;
591}
592
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800593status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
594 if (supportsPause == nullptr || supportsResume == nullptr) {
595 return BAD_VALUE;
596 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000597 TIME_CHECK();
598 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800599 *supportsPause = *supportsResume = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000600 return OK;
601}
602
603status_t StreamOutHalAidl::pause() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800604 return StreamHalAidl::pause();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000605}
606
607status_t StreamOutHalAidl::resume() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800608 return StreamHalAidl::resume();
609}
610
611status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
612 if (supportsDrain == nullptr) {
613 return BAD_VALUE;
614 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000615 TIME_CHECK();
616 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800617 *supportsDrain = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000618 return OK;
619}
620
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800621status_t StreamOutHalAidl::drain(bool earlyNotify) {
622 return StreamHalAidl::drain(earlyNotify);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000623}
624
625status_t StreamOutHalAidl::flush() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800626 return StreamHalAidl::flush();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000627}
628
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800629status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
630 if (frames == nullptr || timestamp == nullptr) {
631 return BAD_VALUE;
632 }
633 int64_t aidlFrames = 0, aidlTimestamp = 0;
634 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
635 return status;
636 }
637 *frames = std::max<int64_t>(0, aidlFrames);
638 timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
639 timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000640 return OK;
641}
642
643status_t StreamOutHalAidl::updateSourceMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800644 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000645 TIME_CHECK();
646 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800647 ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
648 VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
649 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000650}
651
652status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800653 TIME_CHECK();
654 if (!mStream) return NO_INIT;
655 ALOGE("%s not implemented yet", __func__);
656 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000657}
658
659status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800660 TIME_CHECK();
661 if (!mStream) return NO_INIT;
662 ALOGE("%s not implemented yet", __func__);
663 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000664}
665
666status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800667 TIME_CHECK();
668 if (!mStream) return NO_INIT;
669 ALOGE("%s not implemented yet", __func__);
670 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000671}
672
673status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800674 TIME_CHECK();
675 if (!mStream) return NO_INIT;
676 ALOGE("%s not implemented yet", __func__);
677 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000678}
679
680status_t StreamOutHalAidl::getPlaybackRateParameters(
681 audio_playback_rate_t* playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800682 TIME_CHECK();
683 if (!mStream) return NO_INIT;
684 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000685 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000686}
687
688status_t StreamOutHalAidl::setPlaybackRateParameters(
689 const audio_playback_rate_t& playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800690 TIME_CHECK();
691 if (!mStream) return NO_INIT;
692 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000693 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000694}
695
696status_t StreamOutHalAidl::setEventCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800697 const sp<StreamOutHalInterfaceEventCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800698 TIME_CHECK();
699 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800700 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
701 broker->setStreamOutEventCallback(this, callback);
702 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800703 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000704}
705
Mikhail Naganov31d46652023-01-10 18:29:25 +0000706status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800707 TIME_CHECK();
708 if (!mStream) return NO_INIT;
709 ALOGE("%s not implemented yet", __func__);
710 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000711};
712
713status_t StreamOutHalAidl::getRecommendedLatencyModes(
714 std::vector<audio_latency_mode_t> *modes __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800715 TIME_CHECK();
716 if (!mStream) return NO_INIT;
717 ALOGE("%s not implemented yet", __func__);
718 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000719};
720
721status_t StreamOutHalAidl::setLatencyModeCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800722 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800723 TIME_CHECK();
724 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800725 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
726 broker->setStreamOutLatencyModeCallback(this, callback);
727 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800728 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000729};
730
Mikhail Naganov31d46652023-01-10 18:29:25 +0000731status_t StreamOutHalAidl::exit() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800732 return StreamHalAidl::exit();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000733}
734
David Lia0ad9f02023-03-02 21:46:19 +0800735status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
736 TIME_CHECK();
737
738 if (parameters.containsKey(String8(AudioParameter::keyOffloadCodecAverageBitRate)) ||
739 parameters.containsKey(String8(AudioParameter::keyOffloadCodecSampleRate)) ||
740 parameters.containsKey(String8(AudioParameter::keyOffloadCodecChannels)) ||
741 parameters.containsKey(String8(AudioParameter::keyOffloadCodecDelaySamples)) ||
742 parameters.containsKey(String8(AudioParameter::keyOffloadCodecPaddingSamples))) {
743 int value = 0;
744 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecAverageBitRate), value)
745 == NO_ERROR) {
746 if (value <= 0) {
747 return BAD_VALUE;
748 }
749 mOffloadMetadata.averageBitRatePerSecond = value;
750 parameters.remove(String8(AudioParameter::keyOffloadCodecAverageBitRate));
751 }
752
753 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecSampleRate), value)
754 == NO_ERROR) {
755 if (value <= 0) {
756 return BAD_VALUE;
757 }
758 mOffloadMetadata.sampleRate = value;
759 parameters.remove(String8(AudioParameter::keyOffloadCodecSampleRate));
760 }
761
762 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecChannels), value)
763 == NO_ERROR) {
764 if (value <= 0) {
765 return BAD_VALUE;
766 }
767 audio_channel_mask_t channel_mask =
768 audio_channel_out_mask_from_count(static_cast<uint32_t>(value));
769 if (channel_mask == AUDIO_CHANNEL_INVALID) {
770 return BAD_VALUE;
771 }
772 mOffloadMetadata.channelMask =
Mikhail Naganov893b7c22023-03-13 15:48:11 -0700773 VALUE_OR_RETURN_STATUS(
774 ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
775 channel_mask, false));
David Lia0ad9f02023-03-02 21:46:19 +0800776 parameters.remove(String8(AudioParameter::keyOffloadCodecChannels));
777 }
778
779 // The legacy keys are misnamed. The delay and padding are in frame.
780 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecDelaySamples), value)
781 == NO_ERROR) {
782 if (value < 0) {
783 return BAD_VALUE;
784 }
785 mOffloadMetadata.delayFrames = value;
786 parameters.remove(String8(AudioParameter::keyOffloadCodecDelaySamples));
787 }
788
789 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecPaddingSamples), value)
790 == NO_ERROR) {
791 if (value < 0) {
792 return BAD_VALUE;
793 }
794 mOffloadMetadata.paddingFrames = value;
795 parameters.remove(String8(AudioParameter::keyOffloadCodecPaddingSamples));
796 }
797
798 ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
799 status_t status = statusTFromBinderStatus(mStream->updateOffloadMetadata(mOffloadMetadata));
800 if (status != OK) {
801 ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
802 return status;
803 }
804 }
805 return OK;
806}
807
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800808// static
Mikhail Naganov19418e32023-03-10 17:55:14 -0800809ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800810StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
811 ::aidl::android::hardware::audio::common::SinkMetadata aidl;
812 aidl.tracks = VALUE_OR_RETURN(
813 ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
814 legacy.tracks,
815 ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
816 return aidl;
817}
818
Mikhail Naganov31d46652023-01-10 18:29:25 +0000819StreamInHalAidl::StreamInHalAidl(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800820 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
821 const std::shared_ptr<IStreamIn>& stream)
822 : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
823 std::move(context), getStreamCommon(stream)),
Mikhail Naganov31d46652023-01-10 18:29:25 +0000824 mStream(stream) {}
825
826status_t StreamInHalAidl::setGain(float gain __unused) {
827 TIME_CHECK();
828 if (!mStream) return NO_INIT;
829 ALOGE("%s not implemented yet", __func__);
830 return OK;
831}
832
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800833status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
834 if (buffer == nullptr || read == nullptr) {
835 return BAD_VALUE;
836 }
837 return transfer(buffer, bytes, read);
838}
839
840status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
841 if (framesLost == nullptr) {
842 return BAD_VALUE;
843 }
844 int32_t aidlXruns = 0;
845 if (status_t status = getXruns(&aidlXruns); status != OK) {
846 return status;
847 }
848 *framesLost = std::max<int32_t>(0, aidlXruns);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000849 return OK;
850}
851
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800852status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
853 if (frames == nullptr || time == nullptr) {
854 return BAD_VALUE;
855 }
856 return getObservablePosition(frames, time);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000857}
858
859status_t StreamInHalAidl::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -0800860 std::vector<media::MicrophoneInfoFw> *microphones __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800861 TIME_CHECK();
862 if (!mStream) return NO_INIT;
863 ALOGE("%s not implemented yet", __func__);
864 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000865}
866
867status_t StreamInHalAidl::updateSinkMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800868 const StreamInHalInterface::SinkMetadata& sinkMetadata) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800869 TIME_CHECK();
870 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800871 ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
872 VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
873 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000874}
875
876status_t StreamInHalAidl::setPreferredMicrophoneDirection(
877 audio_microphone_direction_t direction __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800878 TIME_CHECK();
879 if (!mStream) return NO_INIT;
880 ALOGE("%s not implemented yet", __func__);
881 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000882}
883
884status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800885 TIME_CHECK();
886 if (!mStream) return NO_INIT;
887 ALOGE("%s not implemented yet", __func__);
888 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000889}
890
891} // namespace android