blob: 49afc113fcd6b703750e6d00d0f57e201f022c6b [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
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700122namespace {
123
124// 'action' must accept a value of type 'T' and return 'status_t'.
125// The function returns 'true' if the parameter was found, and the action has succeeded.
126// The function returns 'false' if the parameter was not found.
127// Any errors get propagated, if there are errors it means the parameter was found.
128template<typename T, typename F>
129error::Result<bool> filterOutAndProcessParameter(
130 AudioParameter& parameters, const String8& key, const F& action) {
131 if (parameters.containsKey(key)) {
132 T value;
133 status_t status = parameters.get(key, value);
134 if (status == OK) {
135 parameters.remove(key);
136 status = action(value);
137 if (status == OK) return true;
138 }
139 return base::unexpected(status);
140 }
141 return false;
142}
143
144} // namespace
145
146status_t StreamHalAidl::setParameters(const String8& kvPairs) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000147 TIME_CHECK();
148 if (!mStream) return NO_INIT;
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700149
150 AudioParameter parameters(kvPairs);
151 ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
152
153 (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
154 parameters, String8(AudioParameter::keyStreamHwAvSync),
155 [&](int hwAvSyncId) {
156 return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
157 }));
158
159 ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
160 __func__, parameters.toString().c_str());
Mikhail Naganov31d46652023-01-10 18:29:25 +0000161 return OK;
162}
163
164status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800165 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000166 TIME_CHECK();
167 values->clear();
168 if (!mStream) return NO_INIT;
169 ALOGE("%s not implemented yet", __func__);
170 return OK;
171}
172
173status_t StreamHalAidl::getFrameSize(size_t *size) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800174 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000175 if (size == nullptr) {
176 return BAD_VALUE;
177 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800178 if (mContext.getFrameSizeBytes() == 0 || !mStream) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000179 return NO_INIT;
180 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800181 *size = mContext.getFrameSizeBytes();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000182 return OK;
183}
184
185status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800186 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000187 TIME_CHECK();
188 if (!mStream) return NO_INIT;
189 ALOGE("%s not implemented yet", __func__);
190 return OK;
191}
192
193status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800194 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000195 TIME_CHECK();
196 if (!mStream) return NO_INIT;
197 ALOGE("%s not implemented yet", __func__);
198 return OK;
199}
200
201status_t StreamHalAidl::standby() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800202 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000203 TIME_CHECK();
204 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800205 const auto state = getState();
206 StreamDescriptor::Reply reply;
207 switch (state) {
208 case StreamDescriptor::State::ACTIVE:
209 if (status_t status = pause(&reply); status != OK) return status;
210 if (reply.state != StreamDescriptor::State::PAUSED) {
211 ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
212 __func__, toString(reply.state).c_str());
213 return INVALID_OPERATION;
214 }
215 FALLTHROUGH_INTENDED;
216 case StreamDescriptor::State::PAUSED:
217 case StreamDescriptor::State::DRAIN_PAUSED:
Jasmine Cha105c66f2023-02-15 16:29:36 +0800218 if (mIsInput) return flush();
219 if (status_t status = flush(&reply); status != OK) return status;
220 if (reply.state != StreamDescriptor::State::IDLE) {
221 ALOGE("%s: unexpected stream state: %s (expected IDLE)",
222 __func__, toString(reply.state).c_str());
223 return INVALID_OPERATION;
224 }
225 FALLTHROUGH_INTENDED;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800226 case StreamDescriptor::State::IDLE:
227 if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
Jasmine Cha105c66f2023-02-15 16:29:36 +0800228 &reply, true /*safeFromNonWorkerThread*/); status != OK) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800229 return status;
230 }
231 if (reply.state != StreamDescriptor::State::STANDBY) {
232 ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
233 __func__, toString(reply.state).c_str());
234 return INVALID_OPERATION;
235 }
236 FALLTHROUGH_INTENDED;
237 case StreamDescriptor::State::STANDBY:
238 return OK;
239 default:
240 ALOGE("%s: not supported from %s stream state %s",
241 __func__, mIsInput ? "input" : "output", toString(state).c_str());
242 return INVALID_OPERATION;
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800243 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000244}
245
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000246status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800247 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000248 TIME_CHECK();
249 if (!mStream) return NO_INIT;
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000250 return mStream->dump(fd, Args(args).args(), args.size());
Mikhail Naganov31d46652023-01-10 18:29:25 +0000251}
252
253status_t StreamHalAidl::start() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800254 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000255 TIME_CHECK();
256 if (!mStream) return NO_INIT;
257 ALOGE("%s not implemented yet", __func__);
258 return OK;
259}
260
261status_t StreamHalAidl::stop() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800262 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
263 TIME_CHECK();
264 if (!mStream) return NO_INIT;
265 ALOGE("%s not implemented yet", __func__);
266 return OK;
267}
268
269status_t StreamHalAidl::getLatency(uint32_t *latency) {
270 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
271 if (!mStream) return NO_INIT;
272 StreamDescriptor::Reply reply;
273 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
274 return status;
275 }
276 *latency = std::max<int32_t>(0, reply.latencyMs);
277 return OK;
278}
279
280status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) {
281 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
282 if (!mStream) return NO_INIT;
283 StreamDescriptor::Reply reply;
284 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
285 return status;
286 }
287 *frames = reply.observable.frames;
288 *timestamp = reply.observable.timeNs;
289 return OK;
290}
291
292status_t StreamHalAidl::getXruns(int32_t *frames) {
293 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
294 if (!mStream) return NO_INIT;
295 StreamDescriptor::Reply reply;
296 if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
297 return status;
298 }
299 *frames = reply.xrunFrames;
300 return OK;
301}
302
303status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
304 ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
Shunkai Yaoc6308712023-02-22 17:53:04 +0000305 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800306 if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
307 mWorkerTid.store(gettid(), std::memory_order_release);
308 // Switch the stream into an active state if needed.
309 // Note: in future we may add support for priming the audio pipeline
310 // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
311 // stream state), however this scenario wasn't supported by the HIDL HAL.
312 if (getState() == StreamDescriptor::State::STANDBY) {
313 StreamDescriptor::Reply reply;
314 if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
315 status != OK) {
316 return status;
317 }
318 if (reply.state != StreamDescriptor::State::IDLE) {
319 ALOGE("%s: failed to get the stream out of standby, actual state: %s",
320 __func__, toString(reply.state).c_str());
321 return INVALID_OPERATION;
322 }
323 }
324 if (!mIsInput) {
325 bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite());
326 }
327 StreamDescriptor::Command burst =
328 StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
329 if (!mIsInput) {
330 if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
331 ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
332 return NOT_ENOUGH_DATA;
333 }
334 }
335 StreamDescriptor::Reply reply;
336 if (status_t status = sendCommand(burst, &reply); status != OK) {
337 return status;
338 }
Jasmine Chaad99fb02023-02-10 12:52:58 +0800339 *transferred = reply.fmqByteCount;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800340 if (mIsInput) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800341 LOG_ALWAYS_FATAL_IF(*transferred > bytes,
342 "%s: HAL module read %zu bytes, which exceeds requested count %zu",
343 __func__, *transferred, bytes);
Jasmine Cha105c66f2023-02-15 16:29:36 +0800344 if (auto toRead = mContext.getDataMQ()->availableToRead();
345 toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
346 ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800347 return NOT_ENOUGH_DATA;
348 }
349 }
350 mStreamPowerLog.log(buffer, *transferred);
351 return OK;
352}
353
354status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
355 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
356 TIME_CHECK();
357 if (!mStream) return NO_INIT;
358 return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
359 true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
360}
361
362status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
363 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
364 TIME_CHECK();
365 if (!mStream) return NO_INIT;
366 if (mIsInput) {
367 return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
368 } else {
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800369 if (mContext.isAsynchronous()) {
370 // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
371 // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
372 const auto state = getState();
373 if (state == StreamDescriptor::State::IDLE) {
374 StreamDescriptor::Reply localReply{};
375 StreamDescriptor::Reply* innerReply = reply ?: &localReply;
376 if (status_t status =
377 sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
378 status != OK) {
379 return status;
380 }
381 if (innerReply->state != StreamDescriptor::State::ACTIVE) {
382 ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
383 __func__, toString(innerReply->state).c_str());
384 return INVALID_OPERATION;
385 }
386 return OK;
387 }
388 }
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800389 return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
390 }
391}
392
393status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
394 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
395 TIME_CHECK();
396 if (!mStream) return NO_INIT;
397 return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
398 mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
399 earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
David Lia6fb5752023-02-23 15:32:47 +0000400 StreamDescriptor::DrainMode::DRAIN_ALL), reply,
401 true /*safeFromNonWorkerThread*/);
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800402}
403
404status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
405 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
406 TIME_CHECK();
407 if (!mStream) return NO_INIT;
408 return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
409 true /*safeFromNonWorkerThread*/); // The workers stops its I/O activity first.
410}
411
412status_t StreamHalAidl::exit() {
413 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000414 TIME_CHECK();
415 if (!mStream) return NO_INIT;
416 ALOGE("%s not implemented yet", __func__);
417 return OK;
418}
419
420status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
421 struct audio_mmap_buffer_info *info __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800422 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000423 TIME_CHECK();
424 if (!mStream) return NO_INIT;
425 ALOGE("%s not implemented yet", __func__);
426 return OK;
427}
428
429status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800430 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000431 TIME_CHECK();
432 if (!mStream) return NO_INIT;
433 ALOGE("%s not implemented yet", __func__);
434 return OK;
435}
436
437status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800438 // Obsolete, must be done by the HAL module.
Mikhail Naganov31d46652023-01-10 18:29:25 +0000439 return OK;
440}
441
442status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800443 ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000444 TIME_CHECK();
445 if (!mStream) return NO_INIT;
446 ALOGE("%s not implemented yet", __func__);
447 return OK;
448}
449
450bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800451 // Obsolete, must be done by the HAL module.
452 return true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000453}
454
455status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
456 std::optional<audio_source_t> source __unused,
457 audio_devices_t type __unused) {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000458 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
459 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000460}
461
462status_t StreamHalAidl::legacyReleaseAudioPatch() {
Mikhail Naganovfab697c2023-01-11 19:33:13 +0000463 // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
464 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000465}
466
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800467status_t StreamHalAidl::sendCommand(
468 const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
469 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
470 bool safeFromNonWorkerThread) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000471 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800472 if (!safeFromNonWorkerThread) {
473 const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
474 LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
475 "%s %s: must be invoked from the worker thread (%d)",
476 __func__, command.toString().c_str(), workerTid);
477 }
478 if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
479 ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
480 return NOT_ENOUGH_DATA;
481 }
482 StreamDescriptor::Reply localReply{};
483 if (reply == nullptr) {
484 reply = &localReply;
485 }
486 if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
487 ALOGE("%s: failed to read from reply MQ, command %s", __func__, command.toString().c_str());
488 return NOT_ENOUGH_DATA;
489 }
490 {
491 std::lock_guard l(mLock);
492 mLastReply = *reply;
493 }
494 switch (reply->status) {
495 case STATUS_OK: return OK;
496 case STATUS_BAD_VALUE: return BAD_VALUE;
497 case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
498 case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
499 default:
500 ALOGE("%s: unexpected status %d returned for command %s",
501 __func__, reply->status, command.toString().c_str());
502 return INVALID_OPERATION;
503 }
504}
505
506status_t StreamHalAidl::updateCountersIfNeeded(
507 ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
508 if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
509 if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
510 state != StreamDescriptor::State::DRAINING &&
511 state != StreamDescriptor::State::TRANSFERRING) {
512 return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
513 }
514 }
515 if (reply != nullptr) {
516 std::lock_guard l(mLock);
517 *reply = mLastReply;
518 }
519 return OK;
520}
521
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800522// static
Mikhail Naganov19418e32023-03-10 17:55:14 -0800523ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800524StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
525 ::aidl::android::hardware::audio::common::SourceMetadata aidl;
526 aidl.tracks = VALUE_OR_RETURN(
527 ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
528 legacy.tracks,
529 ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
530 return aidl;
531}
532
Mikhail Naganov31d46652023-01-10 18:29:25 +0000533StreamOutHalAidl::StreamOutHalAidl(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800534 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800535 const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800536 : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
537 std::move(context), getStreamCommon(stream)),
David Lia0ad9f02023-03-02 21:46:19 +0800538 mStream(stream), mCallbackBroker(callbackBroker) {
539 // Initialize the offload metadata
540 mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
541 mOffloadMetadata.channelMask = VALUE_OR_FATAL(
Mikhail Naganov893b7c22023-03-13 15:48:11 -0700542 ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
543 config.channel_mask, false));
David Lia0ad9f02023-03-02 21:46:19 +0800544 mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
545}
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800546
547StreamOutHalAidl::~StreamOutHalAidl() {
548 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
549 broker->clearCallbacks(this);
550 }
551}
Mikhail Naganov31d46652023-01-10 18:29:25 +0000552
David Lia0ad9f02023-03-02 21:46:19 +0800553status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
554 if (!mStream) return NO_INIT;
555
556 AudioParameter parameters(kvPairs);
557 ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
558
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800559 if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
560 ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
David Lia0ad9f02023-03-02 21:46:19 +0800561 }
562
563 return StreamHalAidl::setParameters(parameters.toString());
564}
565
Mikhail Naganov31d46652023-01-10 18:29:25 +0000566status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800567 return StreamHalAidl::getLatency(latency);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000568}
569
David Lia6fb5752023-02-23 15:32:47 +0000570status_t StreamOutHalAidl::setVolume(float left, float right) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000571 TIME_CHECK();
572 if (!mStream) return NO_INIT;
David Lia6fb5752023-02-23 15:32:47 +0000573 return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000574}
575
576status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
577 TIME_CHECK();
578 if (!mStream) return NO_INIT;
579 ALOGE("%s not implemented yet", __func__);
580 return OK;
581}
582
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800583status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
584 if (buffer == nullptr || written == nullptr) {
585 return BAD_VALUE;
586 }
587 // For the output scenario, 'transfer' does not modify the buffer.
588 return transfer(const_cast<void*>(buffer), bytes, written);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000589}
590
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800591status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
592 if (dspFrames == nullptr) {
593 return BAD_VALUE;
594 }
595 int64_t aidlFrames = 0, aidlTimestamp = 0;
596 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
597 return OK;
598 }
599 *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000600 return OK;
601}
602
603status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800604 // Obsolete, use getPresentationPosition.
605 return INVALID_OPERATION;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000606}
607
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800608status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000609 TIME_CHECK();
610 if (!mStream) return NO_INIT;
Mikhail Naganov712d71b2023-02-23 17:57:16 -0800611 if (!mContext.isAsynchronous()) {
612 ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
613 return INVALID_OPERATION;
614 }
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800615 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
616 if (auto cb = callback.promote(); cb != nullptr) {
617 broker->setStreamOutCallback(this, cb);
618 } else {
619 // It is expected that the framework never passes a null pointer.
620 // In the AIDL model callbacks can't be "unregistered".
621 LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
622 }
623 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000624 return OK;
625}
626
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800627status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
628 if (supportsPause == nullptr || supportsResume == nullptr) {
629 return BAD_VALUE;
630 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000631 TIME_CHECK();
632 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800633 *supportsPause = *supportsResume = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000634 return OK;
635}
636
637status_t StreamOutHalAidl::pause() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800638 return StreamHalAidl::pause();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000639}
640
641status_t StreamOutHalAidl::resume() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800642 return StreamHalAidl::resume();
643}
644
645status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
646 if (supportsDrain == nullptr) {
647 return BAD_VALUE;
648 }
Mikhail Naganov31d46652023-01-10 18:29:25 +0000649 TIME_CHECK();
650 if (!mStream) return NO_INIT;
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800651 *supportsDrain = true;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000652 return OK;
653}
654
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800655status_t StreamOutHalAidl::drain(bool earlyNotify) {
656 return StreamHalAidl::drain(earlyNotify);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000657}
658
659status_t StreamOutHalAidl::flush() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800660 return StreamHalAidl::flush();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000661}
662
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800663status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
664 if (frames == nullptr || timestamp == nullptr) {
665 return BAD_VALUE;
666 }
667 int64_t aidlFrames = 0, aidlTimestamp = 0;
668 if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
669 return status;
670 }
671 *frames = std::max<int64_t>(0, aidlFrames);
672 timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
673 timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000674 return OK;
675}
676
677status_t StreamOutHalAidl::updateSourceMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800678 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
Mikhail Naganov31d46652023-01-10 18:29:25 +0000679 TIME_CHECK();
680 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800681 ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
682 VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
683 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000684}
685
686status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800687 TIME_CHECK();
688 if (!mStream) return NO_INIT;
689 ALOGE("%s not implemented yet", __func__);
690 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000691}
692
693status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800694 TIME_CHECK();
695 if (!mStream) return NO_INIT;
696 ALOGE("%s not implemented yet", __func__);
697 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000698}
699
700status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800701 TIME_CHECK();
702 if (!mStream) return NO_INIT;
703 ALOGE("%s not implemented yet", __func__);
704 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000705}
706
707status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800708 TIME_CHECK();
709 if (!mStream) return NO_INIT;
710 ALOGE("%s not implemented yet", __func__);
711 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000712}
713
714status_t StreamOutHalAidl::getPlaybackRateParameters(
715 audio_playback_rate_t* playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800716 TIME_CHECK();
717 if (!mStream) return NO_INIT;
718 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000719 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000720}
721
722status_t StreamOutHalAidl::setPlaybackRateParameters(
723 const audio_playback_rate_t& playbackRate __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800724 TIME_CHECK();
725 if (!mStream) return NO_INIT;
726 ALOGE("%s not implemented yet", __func__);
David Lia6fb5752023-02-23 15:32:47 +0000727 return BAD_VALUE;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000728}
729
730status_t StreamOutHalAidl::setEventCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800731 const sp<StreamOutHalInterfaceEventCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800732 TIME_CHECK();
733 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800734 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
735 broker->setStreamOutEventCallback(this, callback);
736 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800737 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000738}
739
Mikhail Naganov31d46652023-01-10 18:29:25 +0000740status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800741 TIME_CHECK();
742 if (!mStream) return NO_INIT;
743 ALOGE("%s not implemented yet", __func__);
744 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000745};
746
747status_t StreamOutHalAidl::getRecommendedLatencyModes(
748 std::vector<audio_latency_mode_t> *modes __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800749 TIME_CHECK();
750 if (!mStream) return NO_INIT;
751 ALOGE("%s not implemented yet", __func__);
752 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000753};
754
755status_t StreamOutHalAidl::setLatencyModeCallback(
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800756 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800757 TIME_CHECK();
758 if (!mStream) return NO_INIT;
Mikhail Naganovdfd594e2023-02-08 16:59:41 -0800759 if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
760 broker->setStreamOutLatencyModeCallback(this, callback);
761 }
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800762 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000763};
764
Mikhail Naganov31d46652023-01-10 18:29:25 +0000765status_t StreamOutHalAidl::exit() {
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800766 return StreamHalAidl::exit();
Mikhail Naganov31d46652023-01-10 18:29:25 +0000767}
768
David Lia0ad9f02023-03-02 21:46:19 +0800769status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
770 TIME_CHECK();
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700771 bool updateMetadata = false;
772 if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
773 parameters, String8(AudioParameter::keyOffloadCodecAverageBitRate),
774 [&](int value) {
775 return value > 0 ?
776 mOffloadMetadata.averageBitRatePerSecond = value, OK : BAD_VALUE;
777 }))) {
778 updateMetadata = true;
779 }
780 if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
781 parameters, String8(AudioParameter::keyOffloadCodecSampleRate),
782 [&](int value) {
783 return value > 0 ? mOffloadMetadata.sampleRate = value, OK : BAD_VALUE;
784 }))) {
785 updateMetadata = true;
786 }
787 if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
788 parameters, String8(AudioParameter::keyOffloadCodecChannels),
789 [&](int value) -> status_t {
790 if (value > 0) {
791 audio_channel_mask_t channel_mask = audio_channel_out_mask_from_count(
792 static_cast<uint32_t>(value));
793 if (channel_mask == AUDIO_CHANNEL_INVALID) return BAD_VALUE;
794 mOffloadMetadata.channelMask = VALUE_OR_RETURN_STATUS(
795 ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
796 channel_mask, false /*isInput*/));
797 }
798 return BAD_VALUE;
799 }))) {
800 updateMetadata = true;
801 }
802 if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
803 parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
804 [&](int value) {
805 // The legacy keys are misnamed, the value is in frames.
806 return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
807 }))) {
808 updateMetadata = true;
809 }
810 if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
811 parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
812 [&](int value) {
813 // The legacy keys are misnamed, the value is in frames.
814 return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
815 }))) {
816 updateMetadata = true;
817 }
818 if (updateMetadata) {
David Lia0ad9f02023-03-02 21:46:19 +0800819 ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
Mikhail Naganov08a62ab2023-03-14 17:11:51 -0700820 if (status_t status = statusTFromBinderStatus(
821 mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
David Lia0ad9f02023-03-02 21:46:19 +0800822 ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
823 return status;
824 }
825 }
826 return OK;
827}
828
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800829// static
Mikhail Naganov19418e32023-03-10 17:55:14 -0800830ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800831StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
832 ::aidl::android::hardware::audio::common::SinkMetadata aidl;
833 aidl.tracks = VALUE_OR_RETURN(
834 ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
835 legacy.tracks,
836 ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
837 return aidl;
838}
839
Mikhail Naganov31d46652023-01-10 18:29:25 +0000840StreamInHalAidl::StreamInHalAidl(
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800841 const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
842 const std::shared_ptr<IStreamIn>& stream)
843 : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
844 std::move(context), getStreamCommon(stream)),
Mikhail Naganov31d46652023-01-10 18:29:25 +0000845 mStream(stream) {}
846
847status_t StreamInHalAidl::setGain(float gain __unused) {
848 TIME_CHECK();
849 if (!mStream) return NO_INIT;
850 ALOGE("%s not implemented yet", __func__);
851 return OK;
852}
853
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800854status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
855 if (buffer == nullptr || read == nullptr) {
856 return BAD_VALUE;
857 }
858 return transfer(buffer, bytes, read);
859}
860
861status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
862 if (framesLost == nullptr) {
863 return BAD_VALUE;
864 }
865 int32_t aidlXruns = 0;
866 if (status_t status = getXruns(&aidlXruns); status != OK) {
867 return status;
868 }
869 *framesLost = std::max<int32_t>(0, aidlXruns);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000870 return OK;
871}
872
Mikhail Naganov89a9f742023-01-30 12:33:18 -0800873status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
874 if (frames == nullptr || time == nullptr) {
875 return BAD_VALUE;
876 }
877 return getObservablePosition(frames, time);
Mikhail Naganov31d46652023-01-10 18:29:25 +0000878}
879
880status_t StreamInHalAidl::getActiveMicrophones(
Mikhail Naganov2a6a3012023-02-13 11:45:03 -0800881 std::vector<media::MicrophoneInfoFw> *microphones __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800882 TIME_CHECK();
883 if (!mStream) return NO_INIT;
884 ALOGE("%s not implemented yet", __func__);
885 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000886}
887
888status_t StreamInHalAidl::updateSinkMetadata(
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800889 const StreamInHalInterface::SinkMetadata& sinkMetadata) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800890 TIME_CHECK();
891 if (!mStream) return NO_INIT;
Mikhail Naganovb6e57752023-03-08 18:12:47 -0800892 ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
893 VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
894 return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
Mikhail Naganov31d46652023-01-10 18:29:25 +0000895}
896
897status_t StreamInHalAidl::setPreferredMicrophoneDirection(
898 audio_microphone_direction_t direction __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800899 TIME_CHECK();
900 if (!mStream) return NO_INIT;
901 ALOGE("%s not implemented yet", __func__);
902 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000903}
904
905status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
Mikhail Naganov5b1eed12023-01-25 11:29:11 -0800906 TIME_CHECK();
907 if (!mStream) return NO_INIT;
908 ALOGE("%s not implemented yet", __func__);
909 return OK;
Mikhail Naganov31d46652023-01-10 18:29:25 +0000910}
911
912} // namespace android