blob: 7ad4aab46685477aa8b7884999263fc19ede130c [file] [log] [blame]
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001/*
2 * Copyright (C) 2016 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 "StreamHalHidl"
18//#define LOG_NDEBUG 0
19
Mikhail Naganov247b5f92021-01-15 19:16:12 +000020#include <android/hidl/manager/1.0/IServiceManager.h>
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080021#include <hwbinder/IPCThreadState.h>
Mikhail Naganovac917ac2018-11-28 14:03:52 -080022#include <media/AudioParameter.h>
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080023#include <mediautils/SchedulingPolicyService.h>
24#include <utils/Log.h>
25
Mikhail Naganovea1f19d2022-01-27 22:17:21 +000026#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
Mikhail Naganov247b5f92021-01-15 19:16:12 +000027#include <HidlUtils.h>
28#include <util/CoreUtils.h>
29
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080030#include "DeviceHalHidl.h"
Mikhail Naganov247b5f92021-01-15 19:16:12 +000031#include "ParameterUtils.h"
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080032#include "StreamHalHidl.h"
33
Mikhail Naganovea1f19d2022-01-27 22:17:21 +000034using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
35using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080036using ::android::hardware::MQDescriptorSync;
37using ::android::hardware::Return;
38using ::android::hardware::Void;
Kevin Rocarddf9b4202018-05-10 19:56:08 -070039
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080040namespace android {
41
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080042using ReadCommand = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadCommand;
43
Mikhail Naganovea1f19d2022-01-27 22:17:21 +000044using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
45using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
Mikhail Naganov9ccaa162018-12-12 10:27:29 -080046
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080047StreamHalHidl::StreamHalHidl(IStream *stream)
48 : ConversionHelperHidl("Stream"),
49 mStream(stream),
50 mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT),
51 mCachedBufferSize(0){
52
53 // Instrument audio signal power logging.
54 // Note: This assumes channel mask, format, and sample rate do not change after creation.
Mikhail Naganov247b5f92021-01-15 19:16:12 +000055 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
56 if (/* mStreamPowerLog.isUserDebugOrEngBuild() && */
Mikhail Naganov560637e2021-03-31 22:40:13 +000057 StreamHalHidl::getAudioProperties(&config) == NO_ERROR) {
Mikhail Naganov247b5f92021-01-15 19:16:12 +000058 mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080059 }
60}
61
Andy Hungacb5b982021-01-20 10:12:00 -080062StreamHalHidl::~StreamHalHidl() {
63 // The last step is to flush all binder commands so that the deletion
64 // of IStreamIn / IStreamOut (mStream) is issued with less delay. See b/35394629.
65 hardware::IPCThreadState::self()->flushCommands();
66}
67
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080068status_t StreamHalHidl::getBufferSize(size_t *size) {
69 if (!mStream) return NO_INIT;
70 status_t status = processReturn("getBufferSize", mStream->getBufferSize(), size);
71 if (status == OK) {
72 mCachedBufferSize = *size;
73 }
74 return status;
75}
76
Mikhail Naganov560637e2021-03-31 22:40:13 +000077status_t StreamHalHidl::getAudioProperties(audio_config_base_t *configBase) {
78 *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080079 if (!mStream) return NO_INIT;
Mikhail Naganov247b5f92021-01-15 19:16:12 +000080#if MAJOR_VERSION <= 6
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080081 Return<void> ret = mStream->getAudioProperties(
Kevin Rocardb9cfbf12018-02-23 19:11:06 -080082 [&](uint32_t sr, auto m, auto f) {
Mikhail Naganov560637e2021-03-31 22:40:13 +000083 configBase->sample_rate = sr;
84 configBase->channel_mask = static_cast<audio_channel_mask_t>(m);
85 configBase->format = static_cast<audio_format_t>(f);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -080086 });
87 return processReturn("getAudioProperties", ret);
Mikhail Naganov247b5f92021-01-15 19:16:12 +000088#else
89 Result retval;
90 status_t conversionStatus = BAD_VALUE;
Mikhail Naganov247b5f92021-01-15 19:16:12 +000091 Return<void> ret = mStream->getAudioProperties(
92 [&](Result r, const AudioConfigBase& config) {
93 retval = r;
94 if (retval == Result::OK) {
Mikhail Naganov560637e2021-03-31 22:40:13 +000095 conversionStatus = HidlUtils::audioConfigBaseToHal(config, configBase);
Mikhail Naganov247b5f92021-01-15 19:16:12 +000096 }
97 });
98 if (status_t status = processReturn("getAudioProperties", ret, retval); status == NO_ERROR) {
Mikhail Naganov247b5f92021-01-15 19:16:12 +000099 return conversionStatus;
100 } else {
101 return status;
102 }
103#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800104}
105
106status_t StreamHalHidl::setParameters(const String8& kvPairs) {
107 if (!mStream) return NO_INIT;
108 hidl_vec<ParameterValue> hidlParams;
109 status_t status = parametersFromHal(kvPairs, &hidlParams);
110 if (status != OK) return status;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800111 return processReturn("setParameters",
Dean Wheatley7b417a22019-01-31 20:39:42 +1100112 utils::setParameters(mStream, {} /* context */, hidlParams));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800113}
114
115status_t StreamHalHidl::getParameters(const String8& keys, String8 *values) {
116 values->clear();
117 if (!mStream) return NO_INIT;
118 hidl_vec<hidl_string> hidlKeys;
119 status_t status = keysFromHal(keys, &hidlKeys);
120 if (status != OK) return status;
121 Result retval;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800122 Return<void> ret = utils::getParameters(
123 mStream,
124 {} /* context */,
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800125 hidlKeys,
126 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
127 retval = r;
128 if (retval == Result::OK) {
129 parametersToHal(parameters, values);
130 }
131 });
132 return processReturn("getParameters", ret, retval);
133}
134
135status_t StreamHalHidl::addEffect(sp<EffectHalInterface> effect) {
136 if (!mStream) return NO_INIT;
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000137 return processReturn("addEffect", mStream->addEffect(effect->effectId()));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800138}
139
140status_t StreamHalHidl::removeEffect(sp<EffectHalInterface> effect) {
141 if (!mStream) return NO_INIT;
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000142 return processReturn("removeEffect", mStream->removeEffect(effect->effectId()));
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800143}
144
145status_t StreamHalHidl::standby() {
146 if (!mStream) return NO_INIT;
147 return processReturn("standby", mStream->standby());
148}
149
150status_t StreamHalHidl::dump(int fd) {
151 if (!mStream) return NO_INIT;
152 native_handle_t* hidlHandle = native_handle_create(1, 0);
153 hidlHandle->data[0] = fd;
Kevin Rocardb9cfbf12018-02-23 19:11:06 -0800154 Return<void> ret = mStream->debug(hidlHandle, {} /* options */);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800155 native_handle_delete(hidlHandle);
Andy Hunge72ff022021-08-16 10:16:15 -0700156
157 // TODO(b/111997867, b/177271958) Workaround - remove when fixed.
158 // A Binder transmitted fd may not close immediately due to a race condition b/111997867
159 // when the remote binder thread removes the last refcount to the fd blocks in the
160 // kernel for binder activity. We send a Binder ping() command to unblock the thread
161 // and complete the fd close / release.
162 //
163 // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
164 // EffectsFactoryHalHidl::dumpEffects().
165
166 (void)mStream->ping(); // synchronous Binder call
167
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800168 mStreamPowerLog.dump(fd);
169 return processReturn("dump", ret);
170}
171
172status_t StreamHalHidl::start() {
173 if (!mStream) return NO_INIT;
174 return processReturn("start", mStream->start());
175}
176
177status_t StreamHalHidl::stop() {
178 if (!mStream) return NO_INIT;
179 return processReturn("stop", mStream->stop());
180}
181
182status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
183 struct audio_mmap_buffer_info *info) {
184 Result retval;
185 Return<void> ret = mStream->createMmapBuffer(
186 minSizeFrames,
187 [&](Result r, const MmapBufferInfo& hidlInfo) {
188 retval = r;
189 if (retval == Result::OK) {
190 const native_handle *handle = hidlInfo.sharedMemory.handle();
191 if (handle->numFds > 0) {
192 info->shared_memory_fd = handle->data[0];
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800193#if MAJOR_VERSION >= 4
Kevin Rocard734334f2018-07-12 19:37:41 -0700194 info->flags = audio_mmap_buffer_flag(hidlInfo.flags);
195#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800196 info->buffer_size_frames = hidlInfo.bufferSizeFrames;
Kevin Rocard734334f2018-07-12 19:37:41 -0700197 // Negative buffer size frame was a hack in O and P to
198 // indicate that the buffer is shareable to applications
199 if (info->buffer_size_frames < 0) {
200 info->buffer_size_frames *= -1;
201 info->flags = audio_mmap_buffer_flag(
202 info->flags | AUDIO_MMAP_APPLICATION_SHAREABLE);
203 }
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800204 info->burst_size_frames = hidlInfo.burstSizeFrames;
205 // info->shared_memory_address is not needed in HIDL context
206 info->shared_memory_address = NULL;
207 } else {
208 retval = Result::NOT_INITIALIZED;
209 }
210 }
211 });
212 return processReturn("createMmapBuffer", ret, retval);
213}
214
215status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
216 Result retval;
217 Return<void> ret = mStream->getMmapPosition(
218 [&](Result r, const MmapPosition& hidlPosition) {
219 retval = r;
220 if (retval == Result::OK) {
221 position->time_nanoseconds = hidlPosition.timeNanoseconds;
222 position->position_frames = hidlPosition.positionFrames;
223 }
224 });
225 return processReturn("getMmapPosition", ret, retval);
226}
227
228status_t StreamHalHidl::setHalThreadPriority(int priority) {
229 mHalThreadPriority = priority;
230 return OK;
231}
232
233status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
234 if (mCachedBufferSize != 0) {
235 *size = mCachedBufferSize;
236 return OK;
237 }
238 return getBufferSize(size);
239}
240
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000241status_t StreamHalHidl::getHalPid(pid_t *pid) {
242 using ::android::hidl::base::V1_0::DebugInfo;
243 using ::android::hidl::manager::V1_0::IServiceManager;
244
245 DebugInfo debugInfo;
246 auto ret = mStream->getDebugInfo([&] (const auto &info) {
247 debugInfo = info;
248 });
249 if (!ret.isOk()) {
250 return INVALID_OPERATION;
251 }
252 if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
253 *pid = debugInfo.pid;
254 return NO_ERROR;
255 }
256 return NAME_NOT_FOUND;
257}
258
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800259bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
260 if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
261 return true;
262 }
263 int err = requestPriority(
264 threadPid, threadId,
265 mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
266 ALOGE_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
267 mHalThreadPriority, threadPid, threadId, err);
268 // Audio will still work, but latency will be higher and sometimes unacceptable.
269 return err == 0;
270}
271
272namespace {
273
274/* Notes on callback ownership.
275
276This is how (Hw)Binder ownership model looks like. The server implementation
277is owned by Binder framework (via sp<>). Proxies are owned by clients.
278When the last proxy disappears, Binder framework releases the server impl.
279
280Thus, it is not needed to keep any references to StreamOutCallback (this is
281the server impl) -- it will live as long as HAL server holds a strong ref to
282IStreamOutCallback proxy. We clear that reference by calling 'clearCallback'
283from the destructor of StreamOutHalHidl.
284
285The callback only keeps a weak reference to the stream. The stream is owned
286by AudioFlinger.
287
288*/
289
290struct StreamOutCallback : public IStreamOutCallback {
291 StreamOutCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
292
293 // IStreamOutCallback implementation
294 Return<void> onWriteReady() override {
295 sp<StreamOutHalHidl> stream = mStream.promote();
296 if (stream != 0) {
297 stream->onWriteReady();
298 }
299 return Void();
300 }
301
302 Return<void> onDrainReady() override {
303 sp<StreamOutHalHidl> stream = mStream.promote();
304 if (stream != 0) {
305 stream->onDrainReady();
306 }
307 return Void();
308 }
309
310 Return<void> onError() override {
311 sp<StreamOutHalHidl> stream = mStream.promote();
312 if (stream != 0) {
313 stream->onError();
314 }
315 return Void();
316 }
317
318 private:
Andy Hung638f45b2021-01-18 20:02:56 -0800319 const wp<StreamOutHalHidl> mStream;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800320};
321
322} // namespace
323
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000324StreamOutHalHidl::StreamOutHalHidl(
325 const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& stream)
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800326 : StreamHalHidl(stream.get()), mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
327}
328
329StreamOutHalHidl::~StreamOutHalHidl() {
330 if (mStream != 0) {
Andy Hung638f45b2021-01-18 20:02:56 -0800331 if (mCallback.load().unsafe_get()) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800332 processReturn("clearCallback", mStream->clearCallback());
333 }
jiabinf6eb4c32020-02-25 14:06:25 -0800334#if MAJOR_VERSION >= 6
Andy Hung638f45b2021-01-18 20:02:56 -0800335 if (mEventCallback.load().unsafe_get() != nullptr) {
jiabinf6eb4c32020-02-25 14:06:25 -0800336 processReturn("setEventCallback",
337 mStream->setEventCallback(nullptr));
338 }
339#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800340 processReturn("close", mStream->close());
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800341 }
Andy Hung638f45b2021-01-18 20:02:56 -0800342 mCallback = nullptr;
343 mEventCallback = nullptr;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800344 if (mEfGroup) {
345 EventFlag::deleteEventFlag(&mEfGroup);
346 }
347}
348
349status_t StreamOutHalHidl::getFrameSize(size_t *size) {
350 if (mStream == 0) return NO_INIT;
351 return processReturn("getFrameSize", mStream->getFrameSize(), size);
352}
353
354status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
355 if (mStream == 0) return NO_INIT;
356 if (mWriterClient == gettid() && mCommandMQ) {
357 return callWriterThread(
358 WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
359 [&](const WriteStatus& writeStatus) {
360 *latency = writeStatus.reply.latencyMs;
361 });
362 } else {
363 return processReturn("getLatency", mStream->getLatency(), latency);
364 }
365}
366
367status_t StreamOutHalHidl::setVolume(float left, float right) {
368 if (mStream == 0) return NO_INIT;
369 return processReturn("setVolume", mStream->setVolume(left, right));
370}
371
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800372#if MAJOR_VERSION == 2
373status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
374 if (mStream == 0) return NO_INIT;
375 std::vector<ParameterValue> parameters;
376 String8 halParameters;
377 parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)});
378 parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)});
379 parametersToHal(hidl_vec<ParameterValue>(parameters), &halParameters);
380 return setParameters(halParameters);
381}
Kevin Rocard1cf6b4d2018-11-20 18:05:44 -0800382#elif MAJOR_VERSION >= 4
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800383status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
384 if (mStream == 0) return NO_INIT;
385 return processReturn("selectPresentation",
386 mStream->selectPresentation(presentationId, programId));
387}
388#endif
389
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800390status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
391 if (mStream == 0) return NO_INIT;
392 *written = 0;
393
394 if (bytes == 0 && !mDataMQ) {
395 // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
Andy Hung638f45b2021-01-18 20:02:56 -0800396 ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800397 return OK;
398 }
399
400 status_t status;
401 if (!mDataMQ) {
402 // In case if playback starts close to the end of a compressed track, the bytes
403 // that need to be written is less than the actual buffer size. Need to use
404 // full buffer size for the MQ since otherwise after seeking back to the middle
405 // data will be truncated.
406 size_t bufferSize;
407 if ((status = getCachedBufferSize(&bufferSize)) != OK) {
408 return status;
409 }
410 if (bytes > bufferSize) bufferSize = bytes;
411 if ((status = prepareForWriting(bufferSize)) != OK) {
412 return status;
413 }
414 }
415
416 status = callWriterThread(
417 WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
418 [&] (const WriteStatus& writeStatus) {
419 *written = writeStatus.reply.written;
420 // Diagnostics of the cause of b/35813113.
421 ALOGE_IF(*written > bytes,
422 "hal reports more bytes written than asked for: %lld > %lld",
423 (long long)*written, (long long)bytes);
424 });
425 mStreamPowerLog.log(buffer, *written);
426 return status;
427}
428
429status_t StreamOutHalHidl::callWriterThread(
430 WriteCommand cmd, const char* cmdName,
431 const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
432 if (!mCommandMQ->write(&cmd)) {
433 ALOGE("command message queue write failed for \"%s\"", cmdName);
434 return -EAGAIN;
435 }
436 if (data != nullptr) {
437 size_t availableToWrite = mDataMQ->availableToWrite();
438 if (dataSize > availableToWrite) {
439 ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
440 (long long)dataSize, (long long)availableToWrite);
441 dataSize = availableToWrite;
442 }
443 if (!mDataMQ->write(data, dataSize)) {
444 ALOGE("data message queue write failed for \"%s\"", cmdName);
445 }
446 }
447 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
448
449 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
450 uint32_t efState = 0;
451retry:
452 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
453 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
454 WriteStatus writeStatus;
455 writeStatus.retval = Result::NOT_INITIALIZED;
456 if (!mStatusMQ->read(&writeStatus)) {
457 ALOGE("status message read failed for \"%s\"", cmdName);
458 }
459 if (writeStatus.retval == Result::OK) {
460 ret = OK;
461 callback(writeStatus);
462 } else {
463 ret = processReturn(cmdName, writeStatus.retval);
464 }
465 return ret;
466 }
467 if (ret == -EAGAIN || ret == -EINTR) {
468 // Spurious wakeup. This normally retries no more than once.
469 goto retry;
470 }
471 return ret;
472}
473
474status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
475 std::unique_ptr<CommandMQ> tempCommandMQ;
476 std::unique_ptr<DataMQ> tempDataMQ;
477 std::unique_ptr<StatusMQ> tempStatusMQ;
478 Result retval;
479 pid_t halThreadPid, halThreadTid;
480 Return<void> ret = mStream->prepareForWriting(
481 1, bufferSize,
482 [&](Result r,
483 const CommandMQ::Descriptor& commandMQ,
484 const DataMQ::Descriptor& dataMQ,
485 const StatusMQ::Descriptor& statusMQ,
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000486 const auto& halThreadInfo) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800487 retval = r;
488 if (retval == Result::OK) {
489 tempCommandMQ.reset(new CommandMQ(commandMQ));
490 tempDataMQ.reset(new DataMQ(dataMQ));
491 tempStatusMQ.reset(new StatusMQ(statusMQ));
492 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
493 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
494 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000495#if MAJOR_VERSION <= 6
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800496 halThreadPid = halThreadInfo.pid;
497 halThreadTid = halThreadInfo.tid;
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000498#else
499 halThreadTid = halThreadInfo;
500#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800501 }
502 });
503 if (!ret.isOk() || retval != Result::OK) {
504 return processReturn("prepareForWriting", ret, retval);
505 }
506 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
507 !tempDataMQ || !tempDataMQ->isValid() ||
508 !tempStatusMQ || !tempStatusMQ->isValid() ||
509 !mEfGroup) {
510 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
511 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
512 "Command message queue for writing is invalid");
513 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
514 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
515 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
516 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
517 "Status message queue for writing is invalid");
518 ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
519 return NO_INIT;
520 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000521#if MAJOR_VERSION >= 7
522 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
523 return status;
524 }
525#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800526 requestHalThreadPriority(halThreadPid, halThreadTid);
527
528 mCommandMQ = std::move(tempCommandMQ);
529 mDataMQ = std::move(tempDataMQ);
530 mStatusMQ = std::move(tempStatusMQ);
531 mWriterClient = gettid();
532 return OK;
533}
534
535status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
536 if (mStream == 0) return NO_INIT;
537 Result retval;
538 Return<void> ret = mStream->getRenderPosition(
539 [&](Result r, uint32_t d) {
540 retval = r;
541 if (retval == Result::OK) {
542 *dspFrames = d;
543 }
544 });
545 return processReturn("getRenderPosition", ret, retval);
546}
547
548status_t StreamOutHalHidl::getNextWriteTimestamp(int64_t *timestamp) {
549 if (mStream == 0) return NO_INIT;
550 Result retval;
551 Return<void> ret = mStream->getNextWriteTimestamp(
552 [&](Result r, int64_t t) {
553 retval = r;
554 if (retval == Result::OK) {
555 *timestamp = t;
556 }
557 });
558 return processReturn("getRenderPosition", ret, retval);
559}
560
561status_t StreamOutHalHidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
562 if (mStream == 0) return NO_INIT;
563 status_t status = processReturn(
564 "setCallback", mStream->setCallback(new StreamOutCallback(this)));
565 if (status == OK) {
566 mCallback = callback;
567 }
568 return status;
569}
570
571status_t StreamOutHalHidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
572 if (mStream == 0) return NO_INIT;
573 Return<void> ret = mStream->supportsPauseAndResume(
574 [&](bool p, bool r) {
575 *supportsPause = p;
576 *supportsResume = r;
577 });
578 return processReturn("supportsPauseAndResume", ret);
579}
580
581status_t StreamOutHalHidl::pause() {
582 if (mStream == 0) return NO_INIT;
583 return processReturn("pause", mStream->pause());
584}
585
586status_t StreamOutHalHidl::resume() {
587 if (mStream == 0) return NO_INIT;
588 return processReturn("pause", mStream->resume());
589}
590
591status_t StreamOutHalHidl::supportsDrain(bool *supportsDrain) {
592 if (mStream == 0) return NO_INIT;
593 return processReturn("supportsDrain", mStream->supportsDrain(), supportsDrain);
594}
595
596status_t StreamOutHalHidl::drain(bool earlyNotify) {
597 if (mStream == 0) return NO_INIT;
598 return processReturn(
599 "drain", mStream->drain(earlyNotify ? AudioDrain::EARLY_NOTIFY : AudioDrain::ALL));
600}
601
602status_t StreamOutHalHidl::flush() {
603 if (mStream == 0) return NO_INIT;
604 return processReturn("pause", mStream->flush());
605}
606
607status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
608 if (mStream == 0) return NO_INIT;
609 if (mWriterClient == gettid() && mCommandMQ) {
610 return callWriterThread(
611 WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
612 [&](const WriteStatus& writeStatus) {
613 *frames = writeStatus.reply.presentationPosition.frames;
614 timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
615 timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
616 });
617 } else {
618 Result retval;
619 Return<void> ret = mStream->getPresentationPosition(
620 [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
621 retval = r;
622 if (retval == Result::OK) {
623 *frames = hidlFrames;
624 timestamp->tv_sec = hidlTimeStamp.tvSec;
625 timestamp->tv_nsec = hidlTimeStamp.tvNSec;
626 }
627 });
628 return processReturn("getPresentationPosition", ret, retval);
629 }
630}
631
Kevin Rocard070e7512018-05-22 09:29:13 -0700632#if MAJOR_VERSION == 2
Mikhail Naganov9ccaa162018-12-12 10:27:29 -0800633status_t StreamOutHalHidl::updateSourceMetadata(
634 const StreamOutHalInterface::SourceMetadata& /* sourceMetadata */) {
Kevin Rocard070e7512018-05-22 09:29:13 -0700635 // Audio HAL V2.0 does not support propagating source metadata
636 return INVALID_OPERATION;
637}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800638#elif MAJOR_VERSION >= 4
Mikhail Naganov9ccaa162018-12-12 10:27:29 -0800639status_t StreamOutHalHidl::updateSourceMetadata(
640 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000641#if MAJOR_VERSION == 4
642 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
643#else
644 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
645#endif
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000646 if (status_t status = CoreUtils::sourceMetadataFromHalV7(
647 sourceMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
648 status != OK) {
649 return status;
650 }
651 return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(hidlMetadata));
Kevin Rocarda8975a72018-03-27 10:16:52 -0700652}
Kevin Rocard070e7512018-05-22 09:29:13 -0700653#endif
Kevin Rocarda8975a72018-03-27 10:16:52 -0700654
jiabinf6eb4c32020-02-25 14:06:25 -0800655#if MAJOR_VERSION < 6
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800656status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
657 return INVALID_OPERATION;
658}
659
660status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
661 return INVALID_OPERATION;
662}
663
664status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
665 return INVALID_OPERATION;
666}
667
668status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB __unused) {
669 return INVALID_OPERATION;
670}
671
672status_t StreamOutHalHidl::getPlaybackRateParameters(
673 audio_playback_rate_t* playbackRate __unused) {
674 return INVALID_OPERATION;
675}
676
677status_t StreamOutHalHidl::setPlaybackRateParameters(
678 const audio_playback_rate_t& playbackRate __unused) {
679 return INVALID_OPERATION;
680}
681
jiabinf6eb4c32020-02-25 14:06:25 -0800682status_t StreamOutHalHidl::setEventCallback(
683 const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
684 // Codec format callback is supported starting from audio HAL V6.0
685 return INVALID_OPERATION;
686}
Eric Laurent09a04402022-01-27 21:10:55 +0100687
jiabinf6eb4c32020-02-25 14:06:25 -0800688#else
689
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800690status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
691 if (mStream == 0) return NO_INIT;
692 Result retval;
693 Return<void> ret = mStream->getDualMonoMode(
694 [&](Result r, DualMonoMode hidlMode) {
695 retval = r;
696 if (retval == Result::OK) {
697 *mode = static_cast<audio_dual_mono_mode_t>(hidlMode);
698 }
699 });
700 return processReturn("getDualMonoMode", ret, retval);
701}
702
703status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
704 if (mStream == 0) return NO_INIT;
705 return processReturn(
706 "setDualMonoMode", mStream->setDualMonoMode(static_cast<DualMonoMode>(mode)));
707}
708
709status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB) {
710 if (mStream == 0) return NO_INIT;
711 Result retval;
712 Return<void> ret = mStream->getAudioDescriptionMixLevel(
713 [&](Result r, float hidlLeveldB) {
714 retval = r;
715 if (retval == Result::OK) {
716 *leveldB = hidlLeveldB;
717 }
718 });
719 return processReturn("getAudioDescriptionMixLevel", ret, retval);
720}
721
722status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB) {
723 if (mStream == 0) return NO_INIT;
724 return processReturn(
725 "setAudioDescriptionMixLevel", mStream->setAudioDescriptionMixLevel(leveldB));
726}
727
728status_t StreamOutHalHidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
729 if (mStream == 0) return NO_INIT;
730 Result retval;
731 Return<void> ret = mStream->getPlaybackRateParameters(
732 [&](Result r, PlaybackRate hidlPlaybackRate) {
733 retval = r;
734 if (retval == Result::OK) {
735 playbackRate->mSpeed = hidlPlaybackRate.speed;
736 playbackRate->mPitch = hidlPlaybackRate.pitch;
737 playbackRate->mStretchMode =
738 static_cast<audio_timestretch_stretch_mode_t>(
739 hidlPlaybackRate.timestretchMode);
740 playbackRate->mFallbackMode =
741 static_cast<audio_timestretch_fallback_mode_t>(
742 hidlPlaybackRate.fallbackMode);
743 }
744 });
745 return processReturn("getPlaybackRateParameters", ret, retval);
746}
747
748status_t StreamOutHalHidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
749 if (mStream == 0) return NO_INIT;
750 return processReturn(
751 "setPlaybackRateParameters", mStream->setPlaybackRateParameters(
752 PlaybackRate{playbackRate.mSpeed, playbackRate.mPitch,
753 static_cast<TimestretchMode>(playbackRate.mStretchMode),
754 static_cast<TimestretchFallbackMode>(playbackRate.mFallbackMode)}));
755}
756
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000757#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutEventCallback.h)
jiabinf6eb4c32020-02-25 14:06:25 -0800758
759namespace {
760
761struct StreamOutEventCallback : public IStreamOutEventCallback {
762 StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
763
764 // IStreamOutEventCallback implementation
765 Return<void> onCodecFormatChanged(
766 const android::hardware::hidl_vec<uint8_t>& audioMetadata) override {
767 sp<StreamOutHalHidl> stream = mStream.promote();
768 if (stream != nullptr) {
769 std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
770 stream->onCodecFormatChanged(metadataBs);
771 }
772 return Void();
773 }
774
775 private:
776 wp<StreamOutHalHidl> mStream;
777};
778
779} // namespace
780
781status_t StreamOutHalHidl::setEventCallback(
782 const sp<StreamOutHalInterfaceEventCallback>& callback) {
783 if (mStream == nullptr) return NO_INIT;
784 mEventCallback = callback;
785 status_t status = processReturn(
786 "setEventCallback",
787 mStream->setEventCallback(
788 callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
789 return status;
790}
791#endif
792
Eric Laurent09a04402022-01-27 21:10:55 +0100793#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
794using hardware::audio::V7_1::LatencyMode;
795
796status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode) {
797 if (mStream == 0) return NO_INIT;
798 return processReturn(
799 "setLatencyMode", mStream->setLatencyMode(static_cast<LatencyMode>(mode)));
800};
801
802status_t StreamOutHalHidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
803 if (!mStream) return NO_INIT;
804 Result retval;
805 Return<void> ret = mStream->getRecommendedLatencyModes(
806 [&](Result r, hidl_vec<LatencyMode> hidlModes) {
807 retval = r;
808 for (size_t i = 0; i < hidlModes.size(); i++) {
809 modes->push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
810 }
811 });
812 return processReturn("getRecommendedLatencyModes", ret, retval);
813};
814
815#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutLatencyModeCallback.h)
816
817using hardware::audio::V7_1::IStreamOutLatencyModeCallback;
818
819namespace {
820struct StreamOutLatencyModeCallback : public IStreamOutLatencyModeCallback {
821 StreamOutLatencyModeCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
822
823 // IStreamOutLatencyModeCallback implementation
824 Return<void> onRecommendedLatencyModeChanged(const hidl_vec<LatencyMode>& hidlModes) override {
825 sp<StreamOutHalHidl> stream = mStream.promote();
826 if (stream != nullptr) {
827 std::vector<audio_latency_mode_t> modes;
828 for (size_t i = 0; i < hidlModes.size(); i++) {
829 modes.push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
830 }
831 stream->onRecommendedLatencyModeChanged(modes);
832 }
833 return Void();
834 }
835
836 private:
837 wp<StreamOutHalHidl> mStream;
838};
839} // namespace
840
841status_t StreamOutHalHidl::setLatencyModeCallback(
842 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
843
844 if (mStream == nullptr) return NO_INIT;
845 mLatencyModeCallback = callback;
846 status_t status = processReturn(
847 "setLatencyModeCallback",
848 mStream->setLatencyModeCallback(
849 callback.get() == nullptr ? nullptr : new StreamOutLatencyModeCallback(this)));
850 return status;
851};
852
853#else
854
855status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode __unused) {
856 return INVALID_OPERATION;
857};
858
859status_t StreamOutHalHidl::getRecommendedLatencyModes(
860 std::vector<audio_latency_mode_t> *modes __unused) {
861 return INVALID_OPERATION;
862};
863
864status_t StreamOutHalHidl::setLatencyModeCallback(
865 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
866 return INVALID_OPERATION;
867};
868
869#endif
870
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800871void StreamOutHalHidl::onWriteReady() {
Andy Hung638f45b2021-01-18 20:02:56 -0800872 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800873 if (callback == 0) return;
874 ALOGV("asyncCallback onWriteReady");
875 callback->onWriteReady();
876}
877
878void StreamOutHalHidl::onDrainReady() {
Andy Hung638f45b2021-01-18 20:02:56 -0800879 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800880 if (callback == 0) return;
881 ALOGV("asyncCallback onDrainReady");
882 callback->onDrainReady();
883}
884
885void StreamOutHalHidl::onError() {
Andy Hung638f45b2021-01-18 20:02:56 -0800886 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800887 if (callback == 0) return;
888 ALOGV("asyncCallback onError");
889 callback->onError();
890}
891
jiabinf6eb4c32020-02-25 14:06:25 -0800892void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
Andy Hung638f45b2021-01-18 20:02:56 -0800893 sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
jiabinf6eb4c32020-02-25 14:06:25 -0800894 if (callback == nullptr) return;
895 ALOGV("asyncCodecFormatCallback %s", __func__);
896 callback->onCodecFormatChanged(metadataBs);
897}
898
Eric Laurent09a04402022-01-27 21:10:55 +0100899void StreamOutHalHidl::onRecommendedLatencyModeChanged(
900 const std::vector<audio_latency_mode_t>& modes) {
901 sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
902 if (callback == nullptr) return;
903 callback->onRecommendedLatencyModeChanged(modes);
904}
905
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800906
Mikhail Naganovea1f19d2022-01-27 22:17:21 +0000907StreamInHalHidl::StreamInHalHidl(
908 const sp<::android::hardware::audio::CPP_VERSION::IStreamIn>& stream)
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800909 : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
910}
911
912StreamInHalHidl::~StreamInHalHidl() {
913 if (mStream != 0) {
914 processReturn("close", mStream->close());
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800915 }
916 if (mEfGroup) {
917 EventFlag::deleteEventFlag(&mEfGroup);
918 }
919}
920
921status_t StreamInHalHidl::getFrameSize(size_t *size) {
922 if (mStream == 0) return NO_INIT;
923 return processReturn("getFrameSize", mStream->getFrameSize(), size);
924}
925
926status_t StreamInHalHidl::setGain(float gain) {
927 if (mStream == 0) return NO_INIT;
928 return processReturn("setGain", mStream->setGain(gain));
929}
930
931status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
932 if (mStream == 0) return NO_INIT;
933 *read = 0;
934
935 if (bytes == 0 && !mDataMQ) {
936 // Can't determine the size for the MQ buffer. Wait for a non-empty read request.
937 return OK;
938 }
939
940 status_t status;
941 if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
942 return status;
943 }
944
945 ReadParameters params;
946 params.command = ReadCommand::READ;
947 params.params.read = bytes;
948 status = callReaderThread(params, "read",
949 [&](const ReadStatus& readStatus) {
950 const size_t availToRead = mDataMQ->availableToRead();
951 if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
952 ALOGE("data message queue read failed for \"read\"");
953 }
954 ALOGW_IF(availToRead != readStatus.reply.read,
955 "HAL read report inconsistent: mq = %d, status = %d",
956 (int32_t)availToRead, (int32_t)readStatus.reply.read);
957 *read = readStatus.reply.read;
958 });
959 mStreamPowerLog.log(buffer, *read);
960 return status;
961}
962
963status_t StreamInHalHidl::callReaderThread(
964 const ReadParameters& params, const char* cmdName,
965 StreamInHalHidl::ReaderCallback callback) {
966 if (!mCommandMQ->write(&params)) {
967 ALOGW("command message queue write failed");
968 return -EAGAIN;
969 }
970 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
971
972 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
973 uint32_t efState = 0;
974retry:
975 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
976 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
977 ReadStatus readStatus;
978 readStatus.retval = Result::NOT_INITIALIZED;
979 if (!mStatusMQ->read(&readStatus)) {
980 ALOGE("status message read failed for \"%s\"", cmdName);
981 }
982 if (readStatus.retval == Result::OK) {
983 ret = OK;
984 callback(readStatus);
985 } else {
986 ret = processReturn(cmdName, readStatus.retval);
987 }
988 return ret;
989 }
990 if (ret == -EAGAIN || ret == -EINTR) {
991 // Spurious wakeup. This normally retries no more than once.
992 goto retry;
993 }
994 return ret;
995}
996
997status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
998 std::unique_ptr<CommandMQ> tempCommandMQ;
999 std::unique_ptr<DataMQ> tempDataMQ;
1000 std::unique_ptr<StatusMQ> tempStatusMQ;
1001 Result retval;
1002 pid_t halThreadPid, halThreadTid;
1003 Return<void> ret = mStream->prepareForReading(
1004 1, bufferSize,
1005 [&](Result r,
1006 const CommandMQ::Descriptor& commandMQ,
1007 const DataMQ::Descriptor& dataMQ,
1008 const StatusMQ::Descriptor& statusMQ,
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001009 const auto& halThreadInfo) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001010 retval = r;
1011 if (retval == Result::OK) {
1012 tempCommandMQ.reset(new CommandMQ(commandMQ));
1013 tempDataMQ.reset(new DataMQ(dataMQ));
1014 tempStatusMQ.reset(new StatusMQ(statusMQ));
1015 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
1016 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
1017 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001018#if MAJOR_VERSION <= 6
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001019 halThreadPid = halThreadInfo.pid;
1020 halThreadTid = halThreadInfo.tid;
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001021#else
1022 halThreadTid = halThreadInfo;
1023#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001024 }
1025 });
1026 if (!ret.isOk() || retval != Result::OK) {
1027 return processReturn("prepareForReading", ret, retval);
1028 }
1029 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
1030 !tempDataMQ || !tempDataMQ->isValid() ||
1031 !tempStatusMQ || !tempStatusMQ->isValid() ||
1032 !mEfGroup) {
1033 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
1034 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
1035 "Command message queue for writing is invalid");
1036 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
1037 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
1038 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
1039 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
1040 "Status message queue for reading is invalid");
1041 ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
1042 return NO_INIT;
1043 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001044#if MAJOR_VERSION >= 7
1045 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
1046 return status;
1047 }
1048#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001049 requestHalThreadPriority(halThreadPid, halThreadTid);
1050
1051 mCommandMQ = std::move(tempCommandMQ);
1052 mDataMQ = std::move(tempDataMQ);
1053 mStatusMQ = std::move(tempStatusMQ);
1054 mReaderClient = gettid();
1055 return OK;
1056}
1057
1058status_t StreamInHalHidl::getInputFramesLost(uint32_t *framesLost) {
1059 if (mStream == 0) return NO_INIT;
1060 return processReturn("getInputFramesLost", mStream->getInputFramesLost(), framesLost);
1061}
1062
1063status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
1064 if (mStream == 0) return NO_INIT;
1065 if (mReaderClient == gettid() && mCommandMQ) {
1066 ReadParameters params;
1067 params.command = ReadCommand::GET_CAPTURE_POSITION;
1068 return callReaderThread(params, "getCapturePosition",
1069 [&](const ReadStatus& readStatus) {
1070 *frames = readStatus.reply.capturePosition.frames;
1071 *time = readStatus.reply.capturePosition.time;
1072 });
1073 } else {
1074 Result retval;
1075 Return<void> ret = mStream->getCapturePosition(
1076 [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
1077 retval = r;
1078 if (retval == Result::OK) {
1079 *frames = hidlFrames;
1080 *time = hidlTime;
1081 }
1082 });
1083 return processReturn("getCapturePosition", ret, retval);
1084 }
1085}
1086
Kevin Rocard070e7512018-05-22 09:29:13 -07001087#if MAJOR_VERSION == 2
1088status_t StreamInHalHidl::getActiveMicrophones(
1089 std::vector<media::MicrophoneInfo> *microphones __unused) {
1090 if (mStream == 0) return NO_INIT;
1091 return INVALID_OPERATION;
1092}
1093
Mikhail Naganov9ccaa162018-12-12 10:27:29 -08001094status_t StreamInHalHidl::updateSinkMetadata(
1095 const StreamInHalInterface::SinkMetadata& /* sinkMetadata */) {
Kevin Rocard070e7512018-05-22 09:29:13 -07001096 // Audio HAL V2.0 does not support propagating sink metadata
1097 return INVALID_OPERATION;
1098}
1099
Kevin Rocard3d48dce2018-11-08 17:16:57 -08001100#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -07001101status_t StreamInHalHidl::getActiveMicrophones(
1102 std::vector<media::MicrophoneInfo> *microphonesInfo) {
1103 if (!mStream) return NO_INIT;
1104 Result retval;
1105 Return<void> ret = mStream->getActiveMicrophones(
1106 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
1107 retval = r;
1108 for (size_t k = 0; k < micArrayHal.size(); k++) {
1109 audio_microphone_characteristic_t dst;
1110 // convert
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001111 (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
jiabin9ff780e2018-03-19 18:19:52 -07001112 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
1113 microphonesInfo->push_back(microphone);
1114 }
1115 });
1116 return processReturn("getActiveMicrophones", ret, retval);
1117}
1118
Mikhail Naganov9ccaa162018-12-12 10:27:29 -08001119status_t StreamInHalHidl::updateSinkMetadata(const
1120 StreamInHalInterface::SinkMetadata& sinkMetadata) {
Mikhail Naganovea1f19d2022-01-27 22:17:21 +00001121#if MAJOR_VERSION == 4
1122 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1123#else
1124 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1125#endif
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001126 if (status_t status = CoreUtils::sinkMetadataFromHalV7(
1127 sinkMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
1128 status != OK) {
1129 return status;
1130 }
1131 return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(hidlMetadata));
Kevin Rocarda8975a72018-03-27 10:16:52 -07001132}
Kevin Rocard070e7512018-05-22 09:29:13 -07001133#endif
Kevin Rocarda8975a72018-03-27 10:16:52 -07001134
Paul McLean03a6e6a2018-12-04 10:54:13 -07001135#if MAJOR_VERSION < 5
Paul McLean12340082019-03-19 09:35:05 -06001136status_t StreamInHalHidl::setPreferredMicrophoneDirection(
1137 audio_microphone_direction_t direction __unused) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001138 if (mStream == 0) return NO_INIT;
1139 return INVALID_OPERATION;
1140}
1141
Paul McLean12340082019-03-19 09:35:05 -06001142status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001143 if (mStream == 0) return NO_INIT;
1144 return INVALID_OPERATION;
1145}
1146#else
Paul McLean12340082019-03-19 09:35:05 -06001147status_t StreamInHalHidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001148 if (!mStream) return NO_INIT;
Paul McLean12340082019-03-19 09:35:05 -06001149 return processReturn("setPreferredMicrophoneDirection",
1150 mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
Paul McLean03a6e6a2018-12-04 10:54:13 -07001151}
1152
Paul McLean12340082019-03-19 09:35:05 -06001153status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001154 if (!mStream) return NO_INIT;
Paul McLean12340082019-03-19 09:35:05 -06001155 return processReturn("setPreferredMicrophoneFieldDimension",
Paul McLean03a6e6a2018-12-04 10:54:13 -07001156 mStream->setMicrophoneFieldDimension(zoom));
1157}
1158#endif
1159
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001160} // namespace android