blob: 1c15cfb9a8e1d4b306ea6a0140f499d537c34d1d [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(
508 legacy2aidl_audio_channel_mask_t_AudioChannelLayout(config.channel_mask, false));
509 mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
510}
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800511
512StreamOutHalAidl::~StreamOutHalAidl() {
513 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
514 broker->clearCallbacks(this);
515 }
516}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000517
David Lia0ad9f02023-03-02 21:46:19 +0800518status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
519 if (!mStream) return NO_INIT;
520
521 AudioParameter parameters(kvPairs);
522 ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
523
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800524 if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
525 ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
David Lia0ad9f02023-03-02 21:46:19 +0800526 }
527
528 return StreamHalAidl::setParameters(parameters.toString());
529}
530
Mikhail Naganov31d46652023-01-10 18:29:25 +0000531status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800532 return StreamHalAidl::getLatency(latency);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000533}
534
David Lia6fb5752023-02-23 15:32:47 +0000535status_t StreamOutHalAidl::setVolume(float left, float right) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000536 TIME_CHECK();
537 if (!mStream) return NO_INIT;
David Lia6fb5752023-02-23 15:32:47 +0000538 return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000539}
540
541status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
542 TIME_CHECK();
543 if (!mStream) return NO_INIT;
544 ALOGE("%s not implemented yet", __func__);
545 return OK;
546}
547
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800548status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
549 if (buffer == nullptr || written == nullptr) {
550 return BAD_VALUE;
551 }
552 // For the output scenario, 'transfer' does not modify the buffer.
553 return transfer(const_cast<void*>(buffer), bytes, written);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000554}
555
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800556status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
557 if (dspFrames == nullptr) {
558 return BAD_VALUE;
559 }
560 int64_t aidlFrames = 0, aidlTimestamp = 0;
561 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
562 return OK;
563 }
564 *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000565 return OK;
566}
567
568status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800569 // Obsolete, use getPresentationPosition.
570 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000571}
572
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800573status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000574 TIME_CHECK();
575 if (!mStream) return NO_INIT;
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800576 if (!mContext.isAsynchronous()) {
577 ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
578 return INVALID_OPERATION;
579 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800580 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
581 if (auto cb = callback.promote(); cb != nullptr) {
582 broker->setStreamOutCallback(this, cb);
583 } else {
584 // It is expected that the framework never passes a null pointer.
585 // In the AIDL model callbacks can't be "unregistered".
586 LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
587 }
588 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000589 return OK;
590}
591
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800592status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
593 if (supportsPause == nullptr || supportsResume == nullptr) {
594 return BAD_VALUE;
595 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000596 TIME_CHECK();
597 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800598 *supportsPause = *supportsResume = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000599 return OK;
600}
601
602status_t StreamOutHalAidl::pause() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800603 return StreamHalAidl::pause();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000604}
605
606status_t StreamOutHalAidl::resume() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800607 return StreamHalAidl::resume();
608}
609
610status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
611 if (supportsDrain == nullptr) {
612 return BAD_VALUE;
613 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000614 TIME_CHECK();
615 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800616 *supportsDrain = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000617 return OK;
618}
619
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800620status_t StreamOutHalAidl::drain(bool earlyNotify) {
621 return StreamHalAidl::drain(earlyNotify);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000622}
623
624status_t StreamOutHalAidl::flush() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800625 return StreamHalAidl::flush();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000626}
627
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800628status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
629 if (frames == nullptr || timestamp == nullptr) {
630 return BAD_VALUE;
631 }
632 int64_t aidlFrames = 0, aidlTimestamp = 0;
633 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
634 return status;
635 }
636 *frames = std::max<int64_t>(0, aidlFrames);
637 timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
638 timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000639 return OK;
640}
641
642status_t StreamOutHalAidl::updateSourceMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800643 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000644 TIME_CHECK();
645 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800646 ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
647 VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
648 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000649}
650
651status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800652 TIME_CHECK();
653 if (!mStream) return NO_INIT;
654 ALOGE("%s not implemented yet", __func__);
655 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000656}
657
658status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800659 TIME_CHECK();
660 if (!mStream) return NO_INIT;
661 ALOGE("%s not implemented yet", __func__);
662 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000663}
664
665status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800666 TIME_CHECK();
667 if (!mStream) return NO_INIT;
668 ALOGE("%s not implemented yet", __func__);
669 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000670}
671
672status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800673 TIME_CHECK();
674 if (!mStream) return NO_INIT;
675 ALOGE("%s not implemented yet", __func__);
676 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000677}
678
679status_t StreamOutHalAidl::getPlaybackRateParameters(
680 audio_playback_rate_t* playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800681 TIME_CHECK();
682 if (!mStream) return NO_INIT;
683 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000684 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000685}
686
687status_t StreamOutHalAidl::setPlaybackRateParameters(
688 const audio_playback_rate_t& playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800689 TIME_CHECK();
690 if (!mStream) return NO_INIT;
691 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000692 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000693}
694
695status_t StreamOutHalAidl::setEventCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800696 const sp<StreamOutHalInterfaceEventCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800697 TIME_CHECK();
698 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800699 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
700 broker->setStreamOutEventCallback(this, callback);
701 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800702 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000703}
704
Mikhail Naganov31d46652023-01-10 18:29:25 +0000705status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800706 TIME_CHECK();
707 if (!mStream) return NO_INIT;
708 ALOGE("%s not implemented yet", __func__);
709 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000710};
711
712status_t StreamOutHalAidl::getRecommendedLatencyModes(
713 std::vector<audio_latency_mode_t> *modes __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800714 TIME_CHECK();
715 if (!mStream) return NO_INIT;
716 ALOGE("%s not implemented yet", __func__);
717 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000718};
719
720status_t StreamOutHalAidl::setLatencyModeCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800721 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800722 TIME_CHECK();
723 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800724 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
725 broker->setStreamOutLatencyModeCallback(this, callback);
726 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800727 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000728};
729
Mikhail Naganov31d46652023-01-10 18:29:25 +0000730status_t StreamOutHalAidl::exit() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800731 return StreamHalAidl::exit();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000732}
733
David Lia0ad9f02023-03-02 21:46:19 +0800734status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
735 TIME_CHECK();
736
737 if (parameters.containsKey(String8(AudioParameter::keyOffloadCodecAverageBitRate)) ||
738 parameters.containsKey(String8(AudioParameter::keyOffloadCodecSampleRate)) ||
739 parameters.containsKey(String8(AudioParameter::keyOffloadCodecChannels)) ||
740 parameters.containsKey(String8(AudioParameter::keyOffloadCodecDelaySamples)) ||
741 parameters.containsKey(String8(AudioParameter::keyOffloadCodecPaddingSamples))) {
742 int value = 0;
743 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecAverageBitRate), value)
744 == NO_ERROR) {
745 if (value <= 0) {
746 return BAD_VALUE;
747 }
748 mOffloadMetadata.averageBitRatePerSecond = value;
749 parameters.remove(String8(AudioParameter::keyOffloadCodecAverageBitRate));
750 }
751
752 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecSampleRate), value)
753 == NO_ERROR) {
754 if (value <= 0) {
755 return BAD_VALUE;
756 }
757 mOffloadMetadata.sampleRate = value;
758 parameters.remove(String8(AudioParameter::keyOffloadCodecSampleRate));
759 }
760
761 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecChannels), value)
762 == NO_ERROR) {
763 if (value <= 0) {
764 return BAD_VALUE;
765 }
766 audio_channel_mask_t channel_mask =
767 audio_channel_out_mask_from_count(static_cast<uint32_t>(value));
768 if (channel_mask == AUDIO_CHANNEL_INVALID) {
769 return BAD_VALUE;
770 }
771 mOffloadMetadata.channelMask =
772 VALUE_OR_RETURN_STATUS(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
773 channel_mask, false));
774 parameters.remove(String8(AudioParameter::keyOffloadCodecChannels));
775 }
776
777 // The legacy keys are misnamed. The delay and padding are in frame.
778 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecDelaySamples), value)
779 == NO_ERROR) {
780 if (value < 0) {
781 return BAD_VALUE;
782 }
783 mOffloadMetadata.delayFrames = value;
784 parameters.remove(String8(AudioParameter::keyOffloadCodecDelaySamples));
785 }
786
787 if (parameters.getInt(String8(AudioParameter::keyOffloadCodecPaddingSamples), value)
788 == NO_ERROR) {
789 if (value < 0) {
790 return BAD_VALUE;
791 }
792 mOffloadMetadata.paddingFrames = value;
793 parameters.remove(String8(AudioParameter::keyOffloadCodecPaddingSamples));
794 }
795
796 ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
797 status_t status = statusTFromBinderStatus(mStream->updateOffloadMetadata(mOffloadMetadata));
798 if (status != OK) {
799 ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
800 return status;
801 }
802 }
803 return OK;
804}
805
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800806// static
Mikhail Naganov19418e32023-03-10 17:55:14 -0800807ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800808StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
809 ::aidl::android::hardware::audio::common::SinkMetadata aidl;
810 aidl.tracks = VALUE_OR_RETURN(
811 ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
812 legacy.tracks,
813 ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
814 return aidl;
815}
816
Mikhail Naganov31d46652023-01-10 18:29:25 +0000817StreamInHalAidl::StreamInHalAidl(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800818 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
819 const std::shared_ptr<IStreamIn>& stream)
820 : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
821 std::move(context), getStreamCommon(stream)),
Mikhail Naganov31d46652023-01-10 18:29:25 +0000822 mStream(stream) {}
823
824status_t StreamInHalAidl::setGain(float gain __unused) {
825 TIME_CHECK();
826 if (!mStream) return NO_INIT;
827 ALOGE("%s not implemented yet", __func__);
828 return OK;
829}
830
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800831status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
832 if (buffer == nullptr || read == nullptr) {
833 return BAD_VALUE;
834 }
835 return transfer(buffer, bytes, read);
836}
837
838status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
839 if (framesLost == nullptr) {
840 return BAD_VALUE;
841 }
842 int32_t aidlXruns = 0;
843 if (status_t status = getXruns(&aidlXruns); status != OK) {
844 return status;
845 }
846 *framesLost = std::max<int32_t>(0, aidlXruns);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000847 return OK;
848}
849
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800850status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
851 if (frames == nullptr || time == nullptr) {
852 return BAD_VALUE;
853 }
854 return getObservablePosition(frames, time);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000855}
856
857status_t StreamInHalAidl::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -0800858 std::vector<media::MicrophoneInfoFw> *microphones __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800859 TIME_CHECK();
860 if (!mStream) return NO_INIT;
861 ALOGE("%s not implemented yet", __func__);
862 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000863}
864
865status_t StreamInHalAidl::updateSinkMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800866 const StreamInHalInterface::SinkMetadata& sinkMetadata) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800867 TIME_CHECK();
868 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800869 ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
870 VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
871 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000872}
873
874status_t StreamInHalAidl::setPreferredMicrophoneDirection(
875 audio_microphone_direction_t direction __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800876 TIME_CHECK();
877 if (!mStream) return NO_INIT;
878 ALOGE("%s not implemented yet", __func__);
879 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000880}
881
882status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800883 TIME_CHECK();
884 if (!mStream) return NO_INIT;
885 ALOGE("%s not implemented yet", __func__);
886 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000887}
888
889} // namespace android