blob: b2f1cf35e723354a80f7dc4fa502910a68ad23cc [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 Naganov6718c392022-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 Naganov6718c392022-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 Naganov6718c392022-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 Naganov6718c392022-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 Naganov6718c392022-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
Andy Hung61589a42021-06-16 09:37:53 -0700150status_t StreamHalHidl::dump(int fd, const Vector<String16>& args) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800151 if (!mStream) return NO_INIT;
152 native_handle_t* hidlHandle = native_handle_create(1, 0);
153 hidlHandle->data[0] = fd;
Andy Hung61589a42021-06-16 09:37:53 -0700154 hidl_vec<hidl_string> hidlArgs;
155 argsFromHal(args, &hidlArgs);
156 Return<void> ret = mStream->debug(hidlHandle, hidlArgs);
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800157 native_handle_delete(hidlHandle);
Andy Hunge72ff022021-08-16 10:16:15 -0700158
159 // TODO(b/111997867, b/177271958) Workaround - remove when fixed.
160 // A Binder transmitted fd may not close immediately due to a race condition b/111997867
161 // when the remote binder thread removes the last refcount to the fd blocks in the
162 // kernel for binder activity. We send a Binder ping() command to unblock the thread
163 // and complete the fd close / release.
164 //
165 // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
166 // EffectsFactoryHalHidl::dumpEffects().
167
168 (void)mStream->ping(); // synchronous Binder call
169
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800170 mStreamPowerLog.dump(fd);
171 return processReturn("dump", ret);
172}
173
174status_t StreamHalHidl::start() {
175 if (!mStream) return NO_INIT;
176 return processReturn("start", mStream->start());
177}
178
179status_t StreamHalHidl::stop() {
180 if (!mStream) return NO_INIT;
181 return processReturn("stop", mStream->stop());
182}
183
184status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
185 struct audio_mmap_buffer_info *info) {
186 Result retval;
187 Return<void> ret = mStream->createMmapBuffer(
188 minSizeFrames,
189 [&](Result r, const MmapBufferInfo& hidlInfo) {
190 retval = r;
191 if (retval == Result::OK) {
192 const native_handle *handle = hidlInfo.sharedMemory.handle();
193 if (handle->numFds > 0) {
194 info->shared_memory_fd = handle->data[0];
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800195#if MAJOR_VERSION >= 4
Kevin Rocard734334f2018-07-12 19:37:41 -0700196 info->flags = audio_mmap_buffer_flag(hidlInfo.flags);
197#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800198 info->buffer_size_frames = hidlInfo.bufferSizeFrames;
Kevin Rocard734334f2018-07-12 19:37:41 -0700199 // Negative buffer size frame was a hack in O and P to
200 // indicate that the buffer is shareable to applications
201 if (info->buffer_size_frames < 0) {
202 info->buffer_size_frames *= -1;
203 info->flags = audio_mmap_buffer_flag(
204 info->flags | AUDIO_MMAP_APPLICATION_SHAREABLE);
205 }
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800206 info->burst_size_frames = hidlInfo.burstSizeFrames;
207 // info->shared_memory_address is not needed in HIDL context
208 info->shared_memory_address = NULL;
209 } else {
210 retval = Result::NOT_INITIALIZED;
211 }
212 }
213 });
214 return processReturn("createMmapBuffer", ret, retval);
215}
216
217status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
218 Result retval;
219 Return<void> ret = mStream->getMmapPosition(
220 [&](Result r, const MmapPosition& hidlPosition) {
221 retval = r;
222 if (retval == Result::OK) {
223 position->time_nanoseconds = hidlPosition.timeNanoseconds;
224 position->position_frames = hidlPosition.positionFrames;
225 }
226 });
227 return processReturn("getMmapPosition", ret, retval);
228}
229
230status_t StreamHalHidl::setHalThreadPriority(int priority) {
231 mHalThreadPriority = priority;
232 return OK;
233}
234
235status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
236 if (mCachedBufferSize != 0) {
237 *size = mCachedBufferSize;
238 return OK;
239 }
240 return getBufferSize(size);
241}
242
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000243status_t StreamHalHidl::getHalPid(pid_t *pid) {
244 using ::android::hidl::base::V1_0::DebugInfo;
245 using ::android::hidl::manager::V1_0::IServiceManager;
246
247 DebugInfo debugInfo;
248 auto ret = mStream->getDebugInfo([&] (const auto &info) {
249 debugInfo = info;
250 });
251 if (!ret.isOk()) {
252 return INVALID_OPERATION;
253 }
254 if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
255 *pid = debugInfo.pid;
256 return NO_ERROR;
257 }
258 return NAME_NOT_FOUND;
259}
260
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800261bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
262 if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
263 return true;
264 }
265 int err = requestPriority(
266 threadPid, threadId,
267 mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
268 ALOGE_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
269 mHalThreadPriority, threadPid, threadId, err);
270 // Audio will still work, but latency will be higher and sometimes unacceptable.
271 return err == 0;
272}
273
274namespace {
275
276/* Notes on callback ownership.
277
278This is how (Hw)Binder ownership model looks like. The server implementation
279is owned by Binder framework (via sp<>). Proxies are owned by clients.
280When the last proxy disappears, Binder framework releases the server impl.
281
282Thus, it is not needed to keep any references to StreamOutCallback (this is
283the server impl) -- it will live as long as HAL server holds a strong ref to
284IStreamOutCallback proxy. We clear that reference by calling 'clearCallback'
285from the destructor of StreamOutHalHidl.
286
287The callback only keeps a weak reference to the stream. The stream is owned
288by AudioFlinger.
289
290*/
291
292struct StreamOutCallback : public IStreamOutCallback {
293 StreamOutCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
294
295 // IStreamOutCallback implementation
296 Return<void> onWriteReady() override {
297 sp<StreamOutHalHidl> stream = mStream.promote();
298 if (stream != 0) {
299 stream->onWriteReady();
300 }
301 return Void();
302 }
303
304 Return<void> onDrainReady() override {
305 sp<StreamOutHalHidl> stream = mStream.promote();
306 if (stream != 0) {
307 stream->onDrainReady();
308 }
309 return Void();
310 }
311
312 Return<void> onError() override {
313 sp<StreamOutHalHidl> stream = mStream.promote();
314 if (stream != 0) {
315 stream->onError();
316 }
317 return Void();
318 }
319
320 private:
Andy Hung638f45b2021-01-18 20:02:56 -0800321 const wp<StreamOutHalHidl> mStream;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800322};
323
324} // namespace
325
Mikhail Naganov6718c392022-01-27 22:17:21 +0000326StreamOutHalHidl::StreamOutHalHidl(
327 const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& stream)
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800328 : StreamHalHidl(stream.get()), mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
329}
330
331StreamOutHalHidl::~StreamOutHalHidl() {
332 if (mStream != 0) {
Andy Hung638f45b2021-01-18 20:02:56 -0800333 if (mCallback.load().unsafe_get()) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800334 processReturn("clearCallback", mStream->clearCallback());
335 }
jiabinf6eb4c32020-02-25 14:06:25 -0800336#if MAJOR_VERSION >= 6
Andy Hung638f45b2021-01-18 20:02:56 -0800337 if (mEventCallback.load().unsafe_get() != nullptr) {
jiabinf6eb4c32020-02-25 14:06:25 -0800338 processReturn("setEventCallback",
339 mStream->setEventCallback(nullptr));
340 }
341#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800342 processReturn("close", mStream->close());
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800343 }
Andy Hung638f45b2021-01-18 20:02:56 -0800344 mCallback = nullptr;
345 mEventCallback = nullptr;
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800346 if (mEfGroup) {
347 EventFlag::deleteEventFlag(&mEfGroup);
348 }
349}
350
351status_t StreamOutHalHidl::getFrameSize(size_t *size) {
352 if (mStream == 0) return NO_INIT;
353 return processReturn("getFrameSize", mStream->getFrameSize(), size);
354}
355
356status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
357 if (mStream == 0) return NO_INIT;
358 if (mWriterClient == gettid() && mCommandMQ) {
359 return callWriterThread(
360 WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
361 [&](const WriteStatus& writeStatus) {
362 *latency = writeStatus.reply.latencyMs;
363 });
364 } else {
365 return processReturn("getLatency", mStream->getLatency(), latency);
366 }
367}
368
369status_t StreamOutHalHidl::setVolume(float left, float right) {
370 if (mStream == 0) return NO_INIT;
371 return processReturn("setVolume", mStream->setVolume(left, right));
372}
373
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800374#if MAJOR_VERSION == 2
375status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
376 if (mStream == 0) return NO_INIT;
377 std::vector<ParameterValue> parameters;
378 String8 halParameters;
379 parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)});
380 parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)});
381 parametersToHal(hidl_vec<ParameterValue>(parameters), &halParameters);
382 return setParameters(halParameters);
383}
Kevin Rocard1cf6b4d2018-11-20 18:05:44 -0800384#elif MAJOR_VERSION >= 4
Mikhail Naganovac917ac2018-11-28 14:03:52 -0800385status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
386 if (mStream == 0) return NO_INIT;
387 return processReturn("selectPresentation",
388 mStream->selectPresentation(presentationId, programId));
389}
390#endif
391
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800392status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
393 if (mStream == 0) return NO_INIT;
394 *written = 0;
395
396 if (bytes == 0 && !mDataMQ) {
397 // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
Andy Hung638f45b2021-01-18 20:02:56 -0800398 ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800399 return OK;
400 }
401
402 status_t status;
403 if (!mDataMQ) {
404 // In case if playback starts close to the end of a compressed track, the bytes
405 // that need to be written is less than the actual buffer size. Need to use
406 // full buffer size for the MQ since otherwise after seeking back to the middle
407 // data will be truncated.
408 size_t bufferSize;
409 if ((status = getCachedBufferSize(&bufferSize)) != OK) {
410 return status;
411 }
412 if (bytes > bufferSize) bufferSize = bytes;
413 if ((status = prepareForWriting(bufferSize)) != OK) {
414 return status;
415 }
416 }
417
418 status = callWriterThread(
419 WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
420 [&] (const WriteStatus& writeStatus) {
421 *written = writeStatus.reply.written;
422 // Diagnostics of the cause of b/35813113.
423 ALOGE_IF(*written > bytes,
424 "hal reports more bytes written than asked for: %lld > %lld",
425 (long long)*written, (long long)bytes);
426 });
427 mStreamPowerLog.log(buffer, *written);
428 return status;
429}
430
431status_t StreamOutHalHidl::callWriterThread(
432 WriteCommand cmd, const char* cmdName,
433 const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
434 if (!mCommandMQ->write(&cmd)) {
435 ALOGE("command message queue write failed for \"%s\"", cmdName);
436 return -EAGAIN;
437 }
438 if (data != nullptr) {
439 size_t availableToWrite = mDataMQ->availableToWrite();
440 if (dataSize > availableToWrite) {
441 ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
442 (long long)dataSize, (long long)availableToWrite);
443 dataSize = availableToWrite;
444 }
445 if (!mDataMQ->write(data, dataSize)) {
446 ALOGE("data message queue write failed for \"%s\"", cmdName);
447 }
448 }
449 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
450
451 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
452 uint32_t efState = 0;
453retry:
454 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
455 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
456 WriteStatus writeStatus;
457 writeStatus.retval = Result::NOT_INITIALIZED;
458 if (!mStatusMQ->read(&writeStatus)) {
459 ALOGE("status message read failed for \"%s\"", cmdName);
460 }
461 if (writeStatus.retval == Result::OK) {
462 ret = OK;
463 callback(writeStatus);
464 } else {
465 ret = processReturn(cmdName, writeStatus.retval);
466 }
467 return ret;
468 }
469 if (ret == -EAGAIN || ret == -EINTR) {
470 // Spurious wakeup. This normally retries no more than once.
471 goto retry;
472 }
473 return ret;
474}
475
476status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
477 std::unique_ptr<CommandMQ> tempCommandMQ;
478 std::unique_ptr<DataMQ> tempDataMQ;
479 std::unique_ptr<StatusMQ> tempStatusMQ;
480 Result retval;
481 pid_t halThreadPid, halThreadTid;
482 Return<void> ret = mStream->prepareForWriting(
483 1, bufferSize,
484 [&](Result r,
485 const CommandMQ::Descriptor& commandMQ,
486 const DataMQ::Descriptor& dataMQ,
487 const StatusMQ::Descriptor& statusMQ,
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000488 const auto& halThreadInfo) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800489 retval = r;
490 if (retval == Result::OK) {
491 tempCommandMQ.reset(new CommandMQ(commandMQ));
492 tempDataMQ.reset(new DataMQ(dataMQ));
493 tempStatusMQ.reset(new StatusMQ(statusMQ));
494 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
495 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
496 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000497#if MAJOR_VERSION <= 6
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800498 halThreadPid = halThreadInfo.pid;
499 halThreadTid = halThreadInfo.tid;
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000500#else
501 halThreadTid = halThreadInfo;
502#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800503 }
504 });
505 if (!ret.isOk() || retval != Result::OK) {
506 return processReturn("prepareForWriting", ret, retval);
507 }
508 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
509 !tempDataMQ || !tempDataMQ->isValid() ||
510 !tempStatusMQ || !tempStatusMQ->isValid() ||
511 !mEfGroup) {
512 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
513 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
514 "Command message queue for writing is invalid");
515 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
516 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
517 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
518 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
519 "Status message queue for writing is invalid");
520 ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
521 return NO_INIT;
522 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000523#if MAJOR_VERSION >= 7
524 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
525 return status;
526 }
527#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800528 requestHalThreadPriority(halThreadPid, halThreadTid);
529
530 mCommandMQ = std::move(tempCommandMQ);
531 mDataMQ = std::move(tempDataMQ);
532 mStatusMQ = std::move(tempStatusMQ);
533 mWriterClient = gettid();
534 return OK;
535}
536
537status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
538 if (mStream == 0) return NO_INIT;
539 Result retval;
540 Return<void> ret = mStream->getRenderPosition(
541 [&](Result r, uint32_t d) {
542 retval = r;
543 if (retval == Result::OK) {
544 *dspFrames = d;
545 }
546 });
547 return processReturn("getRenderPosition", ret, retval);
548}
549
550status_t StreamOutHalHidl::getNextWriteTimestamp(int64_t *timestamp) {
551 if (mStream == 0) return NO_INIT;
552 Result retval;
553 Return<void> ret = mStream->getNextWriteTimestamp(
554 [&](Result r, int64_t t) {
555 retval = r;
556 if (retval == Result::OK) {
557 *timestamp = t;
558 }
559 });
560 return processReturn("getRenderPosition", ret, retval);
561}
562
563status_t StreamOutHalHidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
564 if (mStream == 0) return NO_INIT;
565 status_t status = processReturn(
566 "setCallback", mStream->setCallback(new StreamOutCallback(this)));
567 if (status == OK) {
568 mCallback = callback;
569 }
570 return status;
571}
572
573status_t StreamOutHalHidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
574 if (mStream == 0) return NO_INIT;
575 Return<void> ret = mStream->supportsPauseAndResume(
576 [&](bool p, bool r) {
577 *supportsPause = p;
578 *supportsResume = r;
579 });
580 return processReturn("supportsPauseAndResume", ret);
581}
582
583status_t StreamOutHalHidl::pause() {
584 if (mStream == 0) return NO_INIT;
585 return processReturn("pause", mStream->pause());
586}
587
588status_t StreamOutHalHidl::resume() {
589 if (mStream == 0) return NO_INIT;
590 return processReturn("pause", mStream->resume());
591}
592
593status_t StreamOutHalHidl::supportsDrain(bool *supportsDrain) {
594 if (mStream == 0) return NO_INIT;
595 return processReturn("supportsDrain", mStream->supportsDrain(), supportsDrain);
596}
597
598status_t StreamOutHalHidl::drain(bool earlyNotify) {
599 if (mStream == 0) return NO_INIT;
600 return processReturn(
601 "drain", mStream->drain(earlyNotify ? AudioDrain::EARLY_NOTIFY : AudioDrain::ALL));
602}
603
604status_t StreamOutHalHidl::flush() {
605 if (mStream == 0) return NO_INIT;
606 return processReturn("pause", mStream->flush());
607}
608
609status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
610 if (mStream == 0) return NO_INIT;
611 if (mWriterClient == gettid() && mCommandMQ) {
612 return callWriterThread(
613 WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
614 [&](const WriteStatus& writeStatus) {
615 *frames = writeStatus.reply.presentationPosition.frames;
616 timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
617 timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
618 });
619 } else {
620 Result retval;
621 Return<void> ret = mStream->getPresentationPosition(
622 [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
623 retval = r;
624 if (retval == Result::OK) {
625 *frames = hidlFrames;
626 timestamp->tv_sec = hidlTimeStamp.tvSec;
627 timestamp->tv_nsec = hidlTimeStamp.tvNSec;
628 }
629 });
630 return processReturn("getPresentationPosition", ret, retval);
631 }
632}
633
Kevin Rocard070e7512018-05-22 09:29:13 -0700634#if MAJOR_VERSION == 2
Mikhail Naganov9ccaa162018-12-12 10:27:29 -0800635status_t StreamOutHalHidl::updateSourceMetadata(
636 const StreamOutHalInterface::SourceMetadata& /* sourceMetadata */) {
Kevin Rocard070e7512018-05-22 09:29:13 -0700637 // Audio HAL V2.0 does not support propagating source metadata
638 return INVALID_OPERATION;
639}
Kevin Rocard3d48dce2018-11-08 17:16:57 -0800640#elif MAJOR_VERSION >= 4
Mikhail Naganov9ccaa162018-12-12 10:27:29 -0800641status_t StreamOutHalHidl::updateSourceMetadata(
642 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
Mikhail Naganov6718c392022-01-27 22:17:21 +0000643#if MAJOR_VERSION == 4
644 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
645#else
646 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
647#endif
Mikhail Naganov247b5f92021-01-15 19:16:12 +0000648 if (status_t status = CoreUtils::sourceMetadataFromHalV7(
649 sourceMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
650 status != OK) {
651 return status;
652 }
653 return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(hidlMetadata));
Kevin Rocarda8975a72018-03-27 10:16:52 -0700654}
Kevin Rocard070e7512018-05-22 09:29:13 -0700655#endif
Kevin Rocarda8975a72018-03-27 10:16:52 -0700656
jiabinf6eb4c32020-02-25 14:06:25 -0800657#if MAJOR_VERSION < 6
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800658status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
659 return INVALID_OPERATION;
660}
661
662status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
663 return INVALID_OPERATION;
664}
665
666status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
667 return INVALID_OPERATION;
668}
669
670status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB __unused) {
671 return INVALID_OPERATION;
672}
673
674status_t StreamOutHalHidl::getPlaybackRateParameters(
675 audio_playback_rate_t* playbackRate __unused) {
676 return INVALID_OPERATION;
677}
678
679status_t StreamOutHalHidl::setPlaybackRateParameters(
680 const audio_playback_rate_t& playbackRate __unused) {
681 return INVALID_OPERATION;
682}
683
jiabinf6eb4c32020-02-25 14:06:25 -0800684status_t StreamOutHalHidl::setEventCallback(
685 const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
686 // Codec format callback is supported starting from audio HAL V6.0
687 return INVALID_OPERATION;
688}
Eric Laurentafa586b2022-01-27 21:10:55 +0100689
jiabinf6eb4c32020-02-25 14:06:25 -0800690#else
691
Kuowei Lid4adbdb2020-08-13 14:44:25 +0800692status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
693 if (mStream == 0) return NO_INIT;
694 Result retval;
695 Return<void> ret = mStream->getDualMonoMode(
696 [&](Result r, DualMonoMode hidlMode) {
697 retval = r;
698 if (retval == Result::OK) {
699 *mode = static_cast<audio_dual_mono_mode_t>(hidlMode);
700 }
701 });
702 return processReturn("getDualMonoMode", ret, retval);
703}
704
705status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
706 if (mStream == 0) return NO_INIT;
707 return processReturn(
708 "setDualMonoMode", mStream->setDualMonoMode(static_cast<DualMonoMode>(mode)));
709}
710
711status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB) {
712 if (mStream == 0) return NO_INIT;
713 Result retval;
714 Return<void> ret = mStream->getAudioDescriptionMixLevel(
715 [&](Result r, float hidlLeveldB) {
716 retval = r;
717 if (retval == Result::OK) {
718 *leveldB = hidlLeveldB;
719 }
720 });
721 return processReturn("getAudioDescriptionMixLevel", ret, retval);
722}
723
724status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB) {
725 if (mStream == 0) return NO_INIT;
726 return processReturn(
727 "setAudioDescriptionMixLevel", mStream->setAudioDescriptionMixLevel(leveldB));
728}
729
730status_t StreamOutHalHidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
731 if (mStream == 0) return NO_INIT;
732 Result retval;
733 Return<void> ret = mStream->getPlaybackRateParameters(
734 [&](Result r, PlaybackRate hidlPlaybackRate) {
735 retval = r;
736 if (retval == Result::OK) {
737 playbackRate->mSpeed = hidlPlaybackRate.speed;
738 playbackRate->mPitch = hidlPlaybackRate.pitch;
739 playbackRate->mStretchMode =
740 static_cast<audio_timestretch_stretch_mode_t>(
741 hidlPlaybackRate.timestretchMode);
742 playbackRate->mFallbackMode =
743 static_cast<audio_timestretch_fallback_mode_t>(
744 hidlPlaybackRate.fallbackMode);
745 }
746 });
747 return processReturn("getPlaybackRateParameters", ret, retval);
748}
749
750status_t StreamOutHalHidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
751 if (mStream == 0) return NO_INIT;
752 return processReturn(
753 "setPlaybackRateParameters", mStream->setPlaybackRateParameters(
754 PlaybackRate{playbackRate.mSpeed, playbackRate.mPitch,
755 static_cast<TimestretchMode>(playbackRate.mStretchMode),
756 static_cast<TimestretchFallbackMode>(playbackRate.mFallbackMode)}));
757}
758
Mikhail Naganov6718c392022-01-27 22:17:21 +0000759#include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutEventCallback.h)
jiabinf6eb4c32020-02-25 14:06:25 -0800760
761namespace {
762
763struct StreamOutEventCallback : public IStreamOutEventCallback {
764 StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
765
766 // IStreamOutEventCallback implementation
767 Return<void> onCodecFormatChanged(
768 const android::hardware::hidl_vec<uint8_t>& audioMetadata) override {
769 sp<StreamOutHalHidl> stream = mStream.promote();
770 if (stream != nullptr) {
771 std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
772 stream->onCodecFormatChanged(metadataBs);
773 }
774 return Void();
775 }
776
777 private:
778 wp<StreamOutHalHidl> mStream;
779};
780
781} // namespace
782
783status_t StreamOutHalHidl::setEventCallback(
784 const sp<StreamOutHalInterfaceEventCallback>& callback) {
785 if (mStream == nullptr) return NO_INIT;
786 mEventCallback = callback;
787 status_t status = processReturn(
788 "setEventCallback",
789 mStream->setEventCallback(
790 callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
791 return status;
792}
793#endif
794
Eric Laurentafa586b2022-01-27 21:10:55 +0100795#if MAJOR_VERSION == 7 && MINOR_VERSION == 1
796using hardware::audio::V7_1::LatencyMode;
797
798status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode) {
799 if (mStream == 0) return NO_INIT;
800 return processReturn(
801 "setLatencyMode", mStream->setLatencyMode(static_cast<LatencyMode>(mode)));
802};
803
804status_t StreamOutHalHidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
805 if (!mStream) return NO_INIT;
806 Result retval;
807 Return<void> ret = mStream->getRecommendedLatencyModes(
808 [&](Result r, hidl_vec<LatencyMode> hidlModes) {
809 retval = r;
810 for (size_t i = 0; i < hidlModes.size(); i++) {
811 modes->push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
812 }
813 });
814 return processReturn("getRecommendedLatencyModes", ret, retval);
815};
816
817#include PATH(android/hardware/audio/FILE_VERSION/IStreamOutLatencyModeCallback.h)
818
819using hardware::audio::V7_1::IStreamOutLatencyModeCallback;
820
821namespace {
822struct StreamOutLatencyModeCallback : public IStreamOutLatencyModeCallback {
823 StreamOutLatencyModeCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
824
825 // IStreamOutLatencyModeCallback implementation
826 Return<void> onRecommendedLatencyModeChanged(const hidl_vec<LatencyMode>& hidlModes) override {
827 sp<StreamOutHalHidl> stream = mStream.promote();
828 if (stream != nullptr) {
829 std::vector<audio_latency_mode_t> modes;
830 for (size_t i = 0; i < hidlModes.size(); i++) {
831 modes.push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
832 }
833 stream->onRecommendedLatencyModeChanged(modes);
834 }
835 return Void();
836 }
837
838 private:
839 wp<StreamOutHalHidl> mStream;
840};
841} // namespace
842
843status_t StreamOutHalHidl::setLatencyModeCallback(
844 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
845
846 if (mStream == nullptr) return NO_INIT;
847 mLatencyModeCallback = callback;
848 status_t status = processReturn(
849 "setLatencyModeCallback",
850 mStream->setLatencyModeCallback(
851 callback.get() == nullptr ? nullptr : new StreamOutLatencyModeCallback(this)));
852 return status;
853};
854
855#else
856
857status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode __unused) {
858 return INVALID_OPERATION;
859};
860
861status_t StreamOutHalHidl::getRecommendedLatencyModes(
862 std::vector<audio_latency_mode_t> *modes __unused) {
863 return INVALID_OPERATION;
864};
865
866status_t StreamOutHalHidl::setLatencyModeCallback(
867 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
868 return INVALID_OPERATION;
869};
870
871#endif
872
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800873void StreamOutHalHidl::onWriteReady() {
Andy Hung638f45b2021-01-18 20:02:56 -0800874 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800875 if (callback == 0) return;
876 ALOGV("asyncCallback onWriteReady");
877 callback->onWriteReady();
878}
879
880void StreamOutHalHidl::onDrainReady() {
Andy Hung638f45b2021-01-18 20:02:56 -0800881 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800882 if (callback == 0) return;
883 ALOGV("asyncCallback onDrainReady");
884 callback->onDrainReady();
885}
886
887void StreamOutHalHidl::onError() {
Andy Hung638f45b2021-01-18 20:02:56 -0800888 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800889 if (callback == 0) return;
890 ALOGV("asyncCallback onError");
891 callback->onError();
892}
893
jiabinf6eb4c32020-02-25 14:06:25 -0800894void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
Andy Hung638f45b2021-01-18 20:02:56 -0800895 sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
jiabinf6eb4c32020-02-25 14:06:25 -0800896 if (callback == nullptr) return;
897 ALOGV("asyncCodecFormatCallback %s", __func__);
898 callback->onCodecFormatChanged(metadataBs);
899}
900
Eric Laurentafa586b2022-01-27 21:10:55 +0100901void StreamOutHalHidl::onRecommendedLatencyModeChanged(
902 const std::vector<audio_latency_mode_t>& modes) {
903 sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
904 if (callback == nullptr) return;
905 callback->onRecommendedLatencyModeChanged(modes);
906}
907
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800908
Mikhail Naganov6718c392022-01-27 22:17:21 +0000909StreamInHalHidl::StreamInHalHidl(
910 const sp<::android::hardware::audio::CPP_VERSION::IStreamIn>& stream)
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800911 : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
912}
913
914StreamInHalHidl::~StreamInHalHidl() {
915 if (mStream != 0) {
916 processReturn("close", mStream->close());
Kevin Rocard4bcd67f2018-02-28 14:33:38 -0800917 }
918 if (mEfGroup) {
919 EventFlag::deleteEventFlag(&mEfGroup);
920 }
921}
922
923status_t StreamInHalHidl::getFrameSize(size_t *size) {
924 if (mStream == 0) return NO_INIT;
925 return processReturn("getFrameSize", mStream->getFrameSize(), size);
926}
927
928status_t StreamInHalHidl::setGain(float gain) {
929 if (mStream == 0) return NO_INIT;
930 return processReturn("setGain", mStream->setGain(gain));
931}
932
933status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
934 if (mStream == 0) return NO_INIT;
935 *read = 0;
936
937 if (bytes == 0 && !mDataMQ) {
938 // Can't determine the size for the MQ buffer. Wait for a non-empty read request.
939 return OK;
940 }
941
942 status_t status;
943 if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
944 return status;
945 }
946
947 ReadParameters params;
948 params.command = ReadCommand::READ;
949 params.params.read = bytes;
950 status = callReaderThread(params, "read",
951 [&](const ReadStatus& readStatus) {
952 const size_t availToRead = mDataMQ->availableToRead();
953 if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
954 ALOGE("data message queue read failed for \"read\"");
955 }
956 ALOGW_IF(availToRead != readStatus.reply.read,
957 "HAL read report inconsistent: mq = %d, status = %d",
958 (int32_t)availToRead, (int32_t)readStatus.reply.read);
959 *read = readStatus.reply.read;
960 });
961 mStreamPowerLog.log(buffer, *read);
962 return status;
963}
964
965status_t StreamInHalHidl::callReaderThread(
966 const ReadParameters& params, const char* cmdName,
967 StreamInHalHidl::ReaderCallback callback) {
968 if (!mCommandMQ->write(&params)) {
969 ALOGW("command message queue write failed");
970 return -EAGAIN;
971 }
972 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
973
974 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
975 uint32_t efState = 0;
976retry:
977 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
978 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
979 ReadStatus readStatus;
980 readStatus.retval = Result::NOT_INITIALIZED;
981 if (!mStatusMQ->read(&readStatus)) {
982 ALOGE("status message read failed for \"%s\"", cmdName);
983 }
984 if (readStatus.retval == Result::OK) {
985 ret = OK;
986 callback(readStatus);
987 } else {
988 ret = processReturn(cmdName, readStatus.retval);
989 }
990 return ret;
991 }
992 if (ret == -EAGAIN || ret == -EINTR) {
993 // Spurious wakeup. This normally retries no more than once.
994 goto retry;
995 }
996 return ret;
997}
998
999status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
1000 std::unique_ptr<CommandMQ> tempCommandMQ;
1001 std::unique_ptr<DataMQ> tempDataMQ;
1002 std::unique_ptr<StatusMQ> tempStatusMQ;
1003 Result retval;
1004 pid_t halThreadPid, halThreadTid;
1005 Return<void> ret = mStream->prepareForReading(
1006 1, bufferSize,
1007 [&](Result r,
1008 const CommandMQ::Descriptor& commandMQ,
1009 const DataMQ::Descriptor& dataMQ,
1010 const StatusMQ::Descriptor& statusMQ,
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001011 const auto& halThreadInfo) {
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001012 retval = r;
1013 if (retval == Result::OK) {
1014 tempCommandMQ.reset(new CommandMQ(commandMQ));
1015 tempDataMQ.reset(new DataMQ(dataMQ));
1016 tempStatusMQ.reset(new StatusMQ(statusMQ));
1017 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
1018 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
1019 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001020#if MAJOR_VERSION <= 6
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001021 halThreadPid = halThreadInfo.pid;
1022 halThreadTid = halThreadInfo.tid;
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001023#else
1024 halThreadTid = halThreadInfo;
1025#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001026 }
1027 });
1028 if (!ret.isOk() || retval != Result::OK) {
1029 return processReturn("prepareForReading", ret, retval);
1030 }
1031 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
1032 !tempDataMQ || !tempDataMQ->isValid() ||
1033 !tempStatusMQ || !tempStatusMQ->isValid() ||
1034 !mEfGroup) {
1035 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
1036 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
1037 "Command message queue for writing is invalid");
1038 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
1039 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
1040 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
1041 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
1042 "Status message queue for reading is invalid");
1043 ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
1044 return NO_INIT;
1045 }
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001046#if MAJOR_VERSION >= 7
1047 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
1048 return status;
1049 }
1050#endif
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001051 requestHalThreadPriority(halThreadPid, halThreadTid);
1052
1053 mCommandMQ = std::move(tempCommandMQ);
1054 mDataMQ = std::move(tempDataMQ);
1055 mStatusMQ = std::move(tempStatusMQ);
1056 mReaderClient = gettid();
1057 return OK;
1058}
1059
1060status_t StreamInHalHidl::getInputFramesLost(uint32_t *framesLost) {
1061 if (mStream == 0) return NO_INIT;
1062 return processReturn("getInputFramesLost", mStream->getInputFramesLost(), framesLost);
1063}
1064
1065status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
1066 if (mStream == 0) return NO_INIT;
1067 if (mReaderClient == gettid() && mCommandMQ) {
1068 ReadParameters params;
1069 params.command = ReadCommand::GET_CAPTURE_POSITION;
1070 return callReaderThread(params, "getCapturePosition",
1071 [&](const ReadStatus& readStatus) {
1072 *frames = readStatus.reply.capturePosition.frames;
1073 *time = readStatus.reply.capturePosition.time;
1074 });
1075 } else {
1076 Result retval;
1077 Return<void> ret = mStream->getCapturePosition(
1078 [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
1079 retval = r;
1080 if (retval == Result::OK) {
1081 *frames = hidlFrames;
1082 *time = hidlTime;
1083 }
1084 });
1085 return processReturn("getCapturePosition", ret, retval);
1086 }
1087}
1088
Kevin Rocard070e7512018-05-22 09:29:13 -07001089#if MAJOR_VERSION == 2
1090status_t StreamInHalHidl::getActiveMicrophones(
1091 std::vector<media::MicrophoneInfo> *microphones __unused) {
1092 if (mStream == 0) return NO_INIT;
1093 return INVALID_OPERATION;
1094}
1095
Mikhail Naganov9ccaa162018-12-12 10:27:29 -08001096status_t StreamInHalHidl::updateSinkMetadata(
1097 const StreamInHalInterface::SinkMetadata& /* sinkMetadata */) {
Kevin Rocard070e7512018-05-22 09:29:13 -07001098 // Audio HAL V2.0 does not support propagating sink metadata
1099 return INVALID_OPERATION;
1100}
1101
Kevin Rocard3d48dce2018-11-08 17:16:57 -08001102#elif MAJOR_VERSION >= 4
jiabin9ff780e2018-03-19 18:19:52 -07001103status_t StreamInHalHidl::getActiveMicrophones(
1104 std::vector<media::MicrophoneInfo> *microphonesInfo) {
1105 if (!mStream) return NO_INIT;
1106 Result retval;
1107 Return<void> ret = mStream->getActiveMicrophones(
1108 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
1109 retval = r;
1110 for (size_t k = 0; k < micArrayHal.size(); k++) {
1111 audio_microphone_characteristic_t dst;
1112 // convert
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001113 (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
jiabin9ff780e2018-03-19 18:19:52 -07001114 media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
1115 microphonesInfo->push_back(microphone);
1116 }
1117 });
1118 return processReturn("getActiveMicrophones", ret, retval);
1119}
1120
Mikhail Naganov9ccaa162018-12-12 10:27:29 -08001121status_t StreamInHalHidl::updateSinkMetadata(const
1122 StreamInHalInterface::SinkMetadata& sinkMetadata) {
Mikhail Naganov6718c392022-01-27 22:17:21 +00001123#if MAJOR_VERSION == 4
1124 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1125#else
1126 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1127#endif
Mikhail Naganov247b5f92021-01-15 19:16:12 +00001128 if (status_t status = CoreUtils::sinkMetadataFromHalV7(
1129 sinkMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
1130 status != OK) {
1131 return status;
1132 }
1133 return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(hidlMetadata));
Kevin Rocarda8975a72018-03-27 10:16:52 -07001134}
Kevin Rocard070e7512018-05-22 09:29:13 -07001135#endif
Kevin Rocarda8975a72018-03-27 10:16:52 -07001136
Paul McLean03a6e6a2018-12-04 10:54:13 -07001137#if MAJOR_VERSION < 5
Paul McLean12340082019-03-19 09:35:05 -06001138status_t StreamInHalHidl::setPreferredMicrophoneDirection(
1139 audio_microphone_direction_t direction __unused) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001140 if (mStream == 0) return NO_INIT;
1141 return INVALID_OPERATION;
1142}
1143
Paul McLean12340082019-03-19 09:35:05 -06001144status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001145 if (mStream == 0) return NO_INIT;
1146 return INVALID_OPERATION;
1147}
1148#else
Paul McLean12340082019-03-19 09:35:05 -06001149status_t StreamInHalHidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001150 if (!mStream) return NO_INIT;
Paul McLean12340082019-03-19 09:35:05 -06001151 return processReturn("setPreferredMicrophoneDirection",
1152 mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
Paul McLean03a6e6a2018-12-04 10:54:13 -07001153}
1154
Paul McLean12340082019-03-19 09:35:05 -06001155status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom) {
Paul McLean03a6e6a2018-12-04 10:54:13 -07001156 if (!mStream) return NO_INIT;
Paul McLean12340082019-03-19 09:35:05 -06001157 return processReturn("setPreferredMicrophoneFieldDimension",
Paul McLean03a6e6a2018-12-04 10:54:13 -07001158 mStream->setMicrophoneFieldDimension(zoom));
1159}
1160#endif
1161
Kevin Rocard4bcd67f2018-02-28 14:33:38 -08001162} // namespace android