1 /*
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
20 #include <android/hidl/manager/1.0/IServiceManager.h>
21 #include <hwbinder/IPCThreadState.h>
22 #include <media/AudioParameter.h>
23 #include <mediautils/memory.h>
24 #include <mediautils/SchedulingPolicyService.h>
25 #include <mediautils/TimeCheck.h>
26 #include <utils/Log.h>
27 #if MAJOR_VERSION >= 4
28 #include <media/AidlConversion.h>
29 #endif
30
31 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
32 #include <HidlUtils.h>
33 #include <util/CoreUtils.h>
34
35 #include "DeviceHalHidl.h"
36 #include "EffectHalHidl.h"
37 #include "ParameterUtils.h"
38 #include "StreamHalHidl.h"
39
40 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
41 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
42 using ::android::hardware::MQDescriptorSync;
43 using ::android::hardware::Return;
44 using ::android::hardware::Void;
45
46 namespace android {
47
48 using ReadCommand = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadCommand;
49
50 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
51 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
52
StreamHalHidl(std::string_view className,IStream * stream)53 StreamHalHidl::StreamHalHidl(std::string_view className, IStream *stream)
54 : CoreConversionHelperHidl(className),
55 mStream(stream),
56 mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT),
57 mCachedBufferSize(0){
58
59 // Instrument audio signal power logging.
60 // Note: This assumes channel mask, format, and sample rate do not change after creation.
61 audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
62 if (/* mStreamPowerLog.isUserDebugOrEngBuild() && */
63 StreamHalHidl::getAudioProperties(&config) == NO_ERROR) {
64 mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
65 }
66 }
67
~StreamHalHidl()68 StreamHalHidl::~StreamHalHidl() {
69 // The last step is to flush all binder commands so that the deletion
70 // of IStreamIn / IStreamOut (mStream) is issued with less delay. See b/35394629.
71 hardware::IPCThreadState::self()->flushCommands();
72 }
73
getBufferSize(size_t * size)74 status_t StreamHalHidl::getBufferSize(size_t *size) {
75 TIME_CHECK();
76 if (!mStream) return NO_INIT;
77 status_t status = processReturn("getBufferSize", mStream->getBufferSize(), size);
78 if (status == OK) {
79 mCachedBufferSize = *size;
80 }
81 return status;
82 }
83
getAudioProperties(audio_config_base_t * configBase)84 status_t StreamHalHidl::getAudioProperties(audio_config_base_t *configBase) {
85 TIME_CHECK();
86 *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
87 if (!mStream) return NO_INIT;
88 #if MAJOR_VERSION <= 6
89 Return<void> ret = mStream->getAudioProperties(
90 [&](uint32_t sr, auto m, auto f) {
91 configBase->sample_rate = sr;
92 configBase->channel_mask = static_cast<audio_channel_mask_t>(m);
93 configBase->format = static_cast<audio_format_t>(f);
94 });
95 return processReturn("getAudioProperties", ret);
96 #else
97 Result retval;
98 status_t conversionStatus = BAD_VALUE;
99 Return<void> ret = mStream->getAudioProperties(
100 [&](Result r, const AudioConfigBase& config) {
101 retval = r;
102 if (retval == Result::OK) {
103 conversionStatus = HidlUtils::audioConfigBaseToHal(config, configBase);
104 }
105 });
106 if (status_t status = processReturn("getAudioProperties", ret, retval); status == NO_ERROR) {
107 return conversionStatus;
108 } else {
109 return status;
110 }
111 #endif
112 }
113
setParameters(const String8 & kvPairs)114 status_t StreamHalHidl::setParameters(const String8& kvPairs) {
115 TIME_CHECK();
116 if (!mStream) return NO_INIT;
117 hidl_vec<ParameterValue> hidlParams;
118 status_t status = parametersFromHal(kvPairs, &hidlParams);
119 if (status != OK) return status;
120 return processReturn("setParameters",
121 utils::setParameters(mStream, {} /* context */, hidlParams));
122 }
123
getParameters(const String8 & keys,String8 * values)124 status_t StreamHalHidl::getParameters(const String8& keys, String8 *values) {
125 TIME_CHECK();
126 values->clear();
127 if (!mStream) return NO_INIT;
128 hidl_vec<hidl_string> hidlKeys;
129 status_t status = keysFromHal(keys, &hidlKeys);
130 if (status != OK) return status;
131 Result retval;
132 Return<void> ret = utils::getParameters(
133 mStream,
134 {} /* context */,
135 hidlKeys,
136 [&](Result r, const hidl_vec<ParameterValue>& parameters) {
137 retval = r;
138 if (retval == Result::OK) {
139 parametersToHal(parameters, values);
140 }
141 });
142 return processReturn("getParameters", ret, retval);
143 }
144
addEffect(sp<EffectHalInterface> effect)145 status_t StreamHalHidl::addEffect(sp<EffectHalInterface> effect) {
146 TIME_CHECK();
147 if (!mStream) return NO_INIT;
148 auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
149 return processReturn("addEffect", mStream->addEffect(hidlEffect->effectId()));
150 }
151
removeEffect(sp<EffectHalInterface> effect)152 status_t StreamHalHidl::removeEffect(sp<EffectHalInterface> effect) {
153 TIME_CHECK();
154 if (!mStream) return NO_INIT;
155 auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
156 return processReturn("removeEffect", mStream->removeEffect(hidlEffect->effectId()));
157 }
158
standby()159 status_t StreamHalHidl::standby() {
160 TIME_CHECK();
161 if (!mStream) return NO_INIT;
162 return processReturn("standby", mStream->standby());
163 }
164
dump(int fd,const Vector<String16> & args)165 status_t StreamHalHidl::dump(int fd, const Vector<String16>& args) {
166 TIME_CHECK();
167 if (!mStream) return NO_INIT;
168 native_handle_t* hidlHandle = native_handle_create(1, 0);
169 hidlHandle->data[0] = fd;
170 hidl_vec<hidl_string> hidlArgs;
171 argsFromHal(args, &hidlArgs);
172 Return<void> ret = mStream->debug(hidlHandle, hidlArgs);
173 native_handle_delete(hidlHandle);
174
175 // TODO(b/111997867, b/177271958) Workaround - remove when fixed.
176 // A Binder transmitted fd may not close immediately due to a race condition b/111997867
177 // when the remote binder thread removes the last refcount to the fd blocks in the
178 // kernel for binder activity. We send a Binder ping() command to unblock the thread
179 // and complete the fd close / release.
180 //
181 // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
182 // EffectsFactoryHalHidl::dumpEffects().
183
184 (void)mStream->ping(); // synchronous Binder call
185
186 mStreamPowerLog.dump(fd);
187 return processReturn("dump", ret);
188 }
189
start()190 status_t StreamHalHidl::start() {
191 TIME_CHECK();
192 if (!mStream) return NO_INIT;
193 return processReturn("start", mStream->start());
194 }
195
stop()196 status_t StreamHalHidl::stop() {
197 TIME_CHECK();
198 if (!mStream) return NO_INIT;
199 return processReturn("stop", mStream->stop());
200 }
201
createMmapBuffer(int32_t minSizeFrames,struct audio_mmap_buffer_info * info)202 status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
203 struct audio_mmap_buffer_info *info) {
204 TIME_CHECK();
205 Result retval;
206 Return<void> ret = mStream->createMmapBuffer(
207 minSizeFrames,
208 [&](Result r, const MmapBufferInfo& hidlInfo) {
209 retval = r;
210 if (retval == Result::OK) {
211 const native_handle *handle = hidlInfo.sharedMemory.handle();
212 if (handle->numFds > 0) {
213 info->shared_memory_fd = handle->data[0];
214 #if MAJOR_VERSION >= 4
215 info->flags = audio_mmap_buffer_flag(hidlInfo.flags);
216 #endif
217 info->buffer_size_frames = hidlInfo.bufferSizeFrames;
218 // Negative buffer size frame was a hack in O and P to
219 // indicate that the buffer is shareable to applications
220 if (info->buffer_size_frames < 0) {
221 info->buffer_size_frames *= -1;
222 info->flags = audio_mmap_buffer_flag(
223 info->flags | AUDIO_MMAP_APPLICATION_SHAREABLE);
224 }
225 info->burst_size_frames = hidlInfo.burstSizeFrames;
226 // info->shared_memory_address is not needed in HIDL context
227 info->shared_memory_address = NULL;
228 } else {
229 retval = Result::NOT_INITIALIZED;
230 }
231 }
232 });
233 return processReturn("createMmapBuffer", ret, retval);
234 }
235
getMmapPosition(struct audio_mmap_position * position)236 status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
237 TIME_CHECK();
238 Result retval;
239 Return<void> ret = mStream->getMmapPosition(
240 [&](Result r, const MmapPosition& hidlPosition) {
241 retval = r;
242 if (retval == Result::OK) {
243 position->time_nanoseconds = hidlPosition.timeNanoseconds;
244 position->position_frames = hidlPosition.positionFrames;
245 }
246 });
247 return processReturn("getMmapPosition", ret, retval);
248 }
249
setHalThreadPriority(int priority)250 status_t StreamHalHidl::setHalThreadPriority(int priority) {
251 mHalThreadPriority = priority;
252 return OK;
253 }
254
getCachedBufferSize(size_t * size)255 status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
256 if (mCachedBufferSize != 0) {
257 *size = mCachedBufferSize;
258 return OK;
259 }
260 return getBufferSize(size);
261 }
262
getHalPid(pid_t * pid)263 status_t StreamHalHidl::getHalPid(pid_t *pid) {
264 using ::android::hidl::base::V1_0::DebugInfo;
265 using ::android::hidl::manager::V1_0::IServiceManager;
266 TIME_CHECK();
267 DebugInfo debugInfo;
268 auto ret = mStream->getDebugInfo([&] (const auto &info) {
269 debugInfo = info;
270 });
271 if (!ret.isOk()) {
272 return INVALID_OPERATION;
273 }
274 if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
275 *pid = debugInfo.pid;
276 return NO_ERROR;
277 }
278 return NAME_NOT_FOUND;
279 }
280
requestHalThreadPriority(pid_t threadPid,pid_t threadId)281 bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
282 if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
283 return true;
284 }
285 int err = requestPriority(
286 threadPid, threadId,
287 mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
288 ALOGE_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
289 mHalThreadPriority, threadPid, threadId, err);
290 // Audio will still work, but latency will be higher and sometimes unacceptable.
291 return err == 0;
292 }
293
legacyCreateAudioPatch(const struct audio_port_config & port,std::optional<audio_source_t> source,audio_devices_t type)294 status_t StreamHalHidl::legacyCreateAudioPatch(const struct audio_port_config& port,
295 std::optional<audio_source_t> source,
296 audio_devices_t type) {
297 TIME_CHECK();
298 LOG_ALWAYS_FATAL_IF(port.type != AUDIO_PORT_TYPE_DEVICE, "port type must be device");
299 unique_malloced_ptr<char> address;
300 if (strcmp(port.ext.device.address, "") != 0) {
301 // FIXME: we only support address on first sink with HAL version < 3.0
302 address.reset(
303 audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address));
304 } else {
305 address.reset((char*)calloc(1, 1));
306 }
307 AudioParameter param = AudioParameter(String8(address.get()));
308 param.addInt(String8(AudioParameter::keyRouting), (int)type);
309 if (source.has_value()) {
310 param.addInt(String8(AudioParameter::keyInputSource), (int)source.value());
311 }
312 return setParameters(param.toString());
313 }
314
legacyReleaseAudioPatch()315 status_t StreamHalHidl::legacyReleaseAudioPatch() {
316 TIME_CHECK();
317 AudioParameter param;
318 param.addInt(String8(AudioParameter::keyRouting), 0);
319 return setParameters(param.toString());
320 }
321
322 namespace {
323
324 /* Notes on callback ownership.
325
326 This is how (Hw)Binder ownership model looks like. The server implementation
327 is owned by Binder framework (via sp<>). Proxies are owned by clients.
328 When the last proxy disappears, Binder framework releases the server impl.
329
330 Thus, it is not needed to keep any references to StreamOutCallback (this is
331 the server impl) -- it will live as long as HAL server holds a strong ref to
332 IStreamOutCallback proxy. We clear that reference by calling 'clearCallback'
333 from the destructor of StreamOutHalHidl.
334
335 The callback only keeps a weak reference to the stream. The stream is owned
336 by AudioFlinger.
337
338 */
339
340 struct StreamOutCallback : public IStreamOutCallback {
StreamOutCallbackandroid::__anon6103522a0711::StreamOutCallback341 StreamOutCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
342
343 // IStreamOutCallback implementation
onWriteReadyandroid::__anon6103522a0711::StreamOutCallback344 Return<void> onWriteReady() override {
345 sp<StreamOutHalHidl> stream = mStream.promote();
346 if (stream != 0) {
347 stream->onWriteReady();
348 }
349 return Void();
350 }
351
onDrainReadyandroid::__anon6103522a0711::StreamOutCallback352 Return<void> onDrainReady() override {
353 sp<StreamOutHalHidl> stream = mStream.promote();
354 if (stream != 0) {
355 stream->onDrainReady();
356 }
357 return Void();
358 }
359
onErrorandroid::__anon6103522a0711::StreamOutCallback360 Return<void> onError() override {
361 sp<StreamOutHalHidl> stream = mStream.promote();
362 if (stream != 0) {
363 stream->onError();
364 }
365 return Void();
366 }
367
368 private:
369 const wp<StreamOutHalHidl> mStream;
370 };
371
372 } // namespace
373
StreamOutHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IStreamOut> & stream)374 StreamOutHalHidl::StreamOutHalHidl(
375 const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& stream)
376 : StreamHalHidl("StreamOutHalHidl", stream.get())
377 , mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
378 }
379
~StreamOutHalHidl()380 StreamOutHalHidl::~StreamOutHalHidl() {
381 if (mStream != 0) {
382 if (mCallback.load().unsafe_get()) {
383 processReturn("clearCallback", mStream->clearCallback());
384 }
385 #if MAJOR_VERSION >= 6
386 if (mEventCallback.load().unsafe_get() != nullptr) {
387 processReturn("setEventCallback",
388 mStream->setEventCallback(nullptr));
389 }
390 #endif
391 processReturn("close", mStream->close());
392 }
393 mCallback = nullptr;
394 mEventCallback = nullptr;
395 if (mEfGroup) {
396 EventFlag::deleteEventFlag(&mEfGroup);
397 }
398 }
399
getFrameSize(size_t * size)400 status_t StreamOutHalHidl::getFrameSize(size_t *size) {
401 TIME_CHECK();
402 if (mStream == 0) return NO_INIT;
403 return processReturn("getFrameSize", mStream->getFrameSize(), size);
404 }
405
getLatency(uint32_t * latency)406 status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
407 TIME_CHECK();
408 if (mStream == 0) return NO_INIT;
409 if (mWriterClient == gettid() && mCommandMQ) {
410 return callWriterThread(
411 WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
412 [&](const WriteStatus& writeStatus) {
413 *latency = writeStatus.reply.latencyMs;
414 });
415 } else {
416 return processReturn("getLatency", mStream->getLatency(), latency);
417 }
418 }
419
setVolume(float left,float right)420 status_t StreamOutHalHidl::setVolume(float left, float right) {
421 TIME_CHECK();
422 if (mStream == 0) return NO_INIT;
423 return processReturn("setVolume", mStream->setVolume(left, right));
424 }
425
426 #if MAJOR_VERSION == 2
selectPresentation(int presentationId,int programId)427 status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
428 TIME_CHECK();
429 if (mStream == 0) return NO_INIT;
430 std::vector<ParameterValue> parameters;
431 String8 halParameters;
432 parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)});
433 parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)});
434 parametersToHal(hidl_vec<ParameterValue>(parameters), &halParameters);
435 return setParameters(halParameters);
436 }
437 #elif MAJOR_VERSION >= 4
selectPresentation(int presentationId,int programId)438 status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
439 TIME_CHECK();
440 if (mStream == 0) return NO_INIT;
441 return processReturn("selectPresentation",
442 mStream->selectPresentation(presentationId, programId));
443 }
444 #endif
445
write(const void * buffer,size_t bytes,size_t * written)446 status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
447 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
448 if (mStream == 0) return NO_INIT;
449 *written = 0;
450
451 if (bytes == 0 && !mDataMQ) {
452 // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
453 ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
454 return OK;
455 }
456
457 status_t status;
458 if (!mDataMQ) {
459 // In case if playback starts close to the end of a compressed track, the bytes
460 // that need to be written is less than the actual buffer size. Need to use
461 // full buffer size for the MQ since otherwise after seeking back to the middle
462 // data will be truncated.
463 size_t bufferSize;
464 if ((status = getCachedBufferSize(&bufferSize)) != OK) {
465 return status;
466 }
467 if (bytes > bufferSize) bufferSize = bytes;
468 if ((status = prepareForWriting(bufferSize)) != OK) {
469 return status;
470 }
471 }
472
473 status = callWriterThread(
474 WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
475 [&] (const WriteStatus& writeStatus) {
476 *written = writeStatus.reply.written;
477 // Diagnostics of the cause of b/35813113.
478 ALOGE_IF(*written > bytes,
479 "hal reports more bytes written than asked for: %lld > %lld",
480 (long long)*written, (long long)bytes);
481 });
482 mStreamPowerLog.log(buffer, *written);
483 return status;
484 }
485
callWriterThread(WriteCommand cmd,const char * cmdName,const uint8_t * data,size_t dataSize,StreamOutHalHidl::WriterCallback callback)486 status_t StreamOutHalHidl::callWriterThread(
487 WriteCommand cmd, const char* cmdName,
488 const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
489 if (!mCommandMQ->write(&cmd)) {
490 ALOGE("command message queue write failed for \"%s\"", cmdName);
491 return -EAGAIN;
492 }
493 if (data != nullptr) {
494 size_t availableToWrite = mDataMQ->availableToWrite();
495 if (dataSize > availableToWrite) {
496 ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
497 (long long)dataSize, (long long)availableToWrite);
498 dataSize = availableToWrite;
499 }
500 if (!mDataMQ->write(data, dataSize)) {
501 ALOGE("data message queue write failed for \"%s\"", cmdName);
502 }
503 }
504 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
505
506 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
507 uint32_t efState = 0;
508 retry:
509 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
510 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
511 WriteStatus writeStatus;
512 writeStatus.retval = Result::NOT_INITIALIZED;
513 if (!mStatusMQ->read(&writeStatus)) {
514 ALOGE("status message read failed for \"%s\"", cmdName);
515 }
516 if (writeStatus.retval == Result::OK) {
517 ret = OK;
518 callback(writeStatus);
519 } else {
520 ret = processReturn(cmdName, writeStatus.retval);
521 }
522 return ret;
523 }
524 if (ret == -EAGAIN || ret == -EINTR) {
525 // Spurious wakeup. This normally retries no more than once.
526 goto retry;
527 }
528 return ret;
529 }
530
prepareForWriting(size_t bufferSize)531 status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
532 std::unique_ptr<CommandMQ> tempCommandMQ;
533 std::unique_ptr<DataMQ> tempDataMQ;
534 std::unique_ptr<StatusMQ> tempStatusMQ;
535 Result retval;
536 pid_t halThreadPid, halThreadTid;
537 Return<void> ret = mStream->prepareForWriting(
538 1, bufferSize,
539 [&](Result r,
540 const CommandMQ::Descriptor& commandMQ,
541 const DataMQ::Descriptor& dataMQ,
542 const StatusMQ::Descriptor& statusMQ,
543 const auto& halThreadInfo) {
544 retval = r;
545 if (retval == Result::OK) {
546 tempCommandMQ.reset(new CommandMQ(commandMQ));
547 tempDataMQ.reset(new DataMQ(dataMQ));
548 tempStatusMQ.reset(new StatusMQ(statusMQ));
549 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
550 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
551 }
552 #if MAJOR_VERSION <= 6
553 halThreadPid = halThreadInfo.pid;
554 halThreadTid = halThreadInfo.tid;
555 #else
556 halThreadTid = halThreadInfo;
557 #endif
558 }
559 });
560 if (!ret.isOk() || retval != Result::OK) {
561 return processReturn("prepareForWriting", ret, retval);
562 }
563 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
564 !tempDataMQ || !tempDataMQ->isValid() ||
565 !tempStatusMQ || !tempStatusMQ->isValid() ||
566 !mEfGroup) {
567 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
568 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
569 "Command message queue for writing is invalid");
570 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
571 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
572 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
573 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
574 "Status message queue for writing is invalid");
575 ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
576 return NO_INIT;
577 }
578 #if MAJOR_VERSION >= 7
579 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
580 return status;
581 }
582 #endif
583 requestHalThreadPriority(halThreadPid, halThreadTid);
584
585 mCommandMQ = std::move(tempCommandMQ);
586 mDataMQ = std::move(tempDataMQ);
587 mStatusMQ = std::move(tempStatusMQ);
588 mWriterClient = gettid();
589 return OK;
590 }
591
getRenderPosition(uint32_t * dspFrames)592 status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
593 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
594 if (mStream == 0) return NO_INIT;
595 Result retval;
596 Return<void> ret = mStream->getRenderPosition(
597 [&](Result r, uint32_t d) {
598 retval = r;
599 if (retval == Result::OK) {
600 *dspFrames = d;
601 }
602 });
603 return processReturn("getRenderPosition", ret, retval);
604 }
605
getNextWriteTimestamp(int64_t * timestamp)606 status_t StreamOutHalHidl::getNextWriteTimestamp(int64_t *timestamp) {
607 TIME_CHECK();
608 if (mStream == 0) return NO_INIT;
609 Result retval;
610 Return<void> ret = mStream->getNextWriteTimestamp(
611 [&](Result r, int64_t t) {
612 retval = r;
613 if (retval == Result::OK) {
614 *timestamp = t;
615 }
616 });
617 return processReturn("getRenderPosition", ret, retval);
618 }
619
setCallback(wp<StreamOutHalInterfaceCallback> callback)620 status_t StreamOutHalHidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
621 TIME_CHECK();
622 if (mStream == 0) return NO_INIT;
623 status_t status = processReturn(
624 "setCallback", mStream->setCallback(new StreamOutCallback(this)));
625 if (status == OK) {
626 mCallback = callback;
627 }
628 return status;
629 }
630
supportsPauseAndResume(bool * supportsPause,bool * supportsResume)631 status_t StreamOutHalHidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
632 TIME_CHECK();
633 if (mStream == 0) return NO_INIT;
634 Return<void> ret = mStream->supportsPauseAndResume(
635 [&](bool p, bool r) {
636 *supportsPause = p;
637 *supportsResume = r;
638 });
639 return processReturn("supportsPauseAndResume", ret);
640 }
641
pause()642 status_t StreamOutHalHidl::pause() {
643 TIME_CHECK();
644 if (mStream == 0) return NO_INIT;
645 return processReturn("pause", mStream->pause());
646 }
647
resume()648 status_t StreamOutHalHidl::resume() {
649 TIME_CHECK();
650 if (mStream == 0) return NO_INIT;
651 return processReturn("pause", mStream->resume());
652 }
653
supportsDrain(bool * supportsDrain)654 status_t StreamOutHalHidl::supportsDrain(bool *supportsDrain) {
655 TIME_CHECK();
656 if (mStream == 0) return NO_INIT;
657 return processReturn("supportsDrain", mStream->supportsDrain(), supportsDrain);
658 }
659
drain(bool earlyNotify)660 status_t StreamOutHalHidl::drain(bool earlyNotify) {
661 TIME_CHECK();
662 if (mStream == 0) return NO_INIT;
663 return processReturn(
664 "drain", mStream->drain(earlyNotify ? AudioDrain::EARLY_NOTIFY : AudioDrain::ALL));
665 }
666
flush()667 status_t StreamOutHalHidl::flush() {
668 TIME_CHECK();
669 if (mStream == 0) return NO_INIT;
670 return processReturn("pause", mStream->flush());
671 }
672
getPresentationPosition(uint64_t * frames,struct timespec * timestamp)673 status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
674 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
675 if (mStream == 0) return NO_INIT;
676 if (mWriterClient == gettid() && mCommandMQ) {
677 return callWriterThread(
678 WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
679 [&](const WriteStatus& writeStatus) {
680 *frames = writeStatus.reply.presentationPosition.frames;
681 timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
682 timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
683 });
684 } else {
685 Result retval;
686 Return<void> ret = mStream->getPresentationPosition(
687 [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
688 retval = r;
689 if (retval == Result::OK) {
690 *frames = hidlFrames;
691 timestamp->tv_sec = hidlTimeStamp.tvSec;
692 timestamp->tv_nsec = hidlTimeStamp.tvNSec;
693 }
694 });
695 return processReturn("getPresentationPosition", ret, retval);
696 }
697 }
698
699 #if MAJOR_VERSION == 2
updateSourceMetadata(const StreamOutHalInterface::SourceMetadata &)700 status_t StreamOutHalHidl::updateSourceMetadata(
701 const StreamOutHalInterface::SourceMetadata& /* sourceMetadata */) {
702 // Audio HAL V2.0 does not support propagating source metadata
703 return INVALID_OPERATION;
704 }
705 #elif MAJOR_VERSION >= 4
updateSourceMetadata(const StreamOutHalInterface::SourceMetadata & sourceMetadata)706 status_t StreamOutHalHidl::updateSourceMetadata(
707 const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
708 TIME_CHECK();
709 #if MAJOR_VERSION == 4
710 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
711 #else
712 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
713 #endif
714 if (status_t status = CoreUtils::sourceMetadataFromHalV7(
715 sourceMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
716 status != OK) {
717 return status;
718 }
719 return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(hidlMetadata));
720 }
721 #endif
722
723 #if MAJOR_VERSION < 6
getDualMonoMode(audio_dual_mono_mode_t * mode __unused)724 status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
725 return INVALID_OPERATION;
726 }
727
setDualMonoMode(audio_dual_mono_mode_t mode __unused)728 status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
729 return INVALID_OPERATION;
730 }
731
getAudioDescriptionMixLevel(float * leveldB __unused)732 status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
733 return INVALID_OPERATION;
734 }
735
setAudioDescriptionMixLevel(float leveldB __unused)736 status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB __unused) {
737 return INVALID_OPERATION;
738 }
739
getPlaybackRateParameters(audio_playback_rate_t * playbackRate __unused)740 status_t StreamOutHalHidl::getPlaybackRateParameters(
741 audio_playback_rate_t* playbackRate __unused) {
742 return INVALID_OPERATION;
743 }
744
setPlaybackRateParameters(const audio_playback_rate_t & playbackRate __unused)745 status_t StreamOutHalHidl::setPlaybackRateParameters(
746 const audio_playback_rate_t& playbackRate __unused) {
747 return INVALID_OPERATION;
748 }
749
setEventCallback(const sp<StreamOutHalInterfaceEventCallback> & callback __unused)750 status_t StreamOutHalHidl::setEventCallback(
751 const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
752 // Codec format callback is supported starting from audio HAL V6.0
753 return INVALID_OPERATION;
754 }
755
756 #else
757
getDualMonoMode(audio_dual_mono_mode_t * mode)758 status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
759 TIME_CHECK();
760 if (mStream == 0) return NO_INIT;
761 Result retval;
762 Return<void> ret = mStream->getDualMonoMode(
763 [&](Result r, DualMonoMode hidlMode) {
764 retval = r;
765 if (retval == Result::OK) {
766 *mode = static_cast<audio_dual_mono_mode_t>(hidlMode);
767 }
768 });
769 return processReturn("getDualMonoMode", ret, retval);
770 }
771
setDualMonoMode(audio_dual_mono_mode_t mode)772 status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
773 TIME_CHECK();
774 if (mStream == 0) return NO_INIT;
775 return processReturn(
776 "setDualMonoMode", mStream->setDualMonoMode(static_cast<DualMonoMode>(mode)));
777 }
778
getAudioDescriptionMixLevel(float * leveldB)779 status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB) {
780 TIME_CHECK();
781 if (mStream == 0) return NO_INIT;
782 Result retval;
783 Return<void> ret = mStream->getAudioDescriptionMixLevel(
784 [&](Result r, float hidlLeveldB) {
785 retval = r;
786 if (retval == Result::OK) {
787 *leveldB = hidlLeveldB;
788 }
789 });
790 return processReturn("getAudioDescriptionMixLevel", ret, retval);
791 }
792
setAudioDescriptionMixLevel(float leveldB)793 status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB) {
794 TIME_CHECK();
795 if (mStream == 0) return NO_INIT;
796 return processReturn(
797 "setAudioDescriptionMixLevel", mStream->setAudioDescriptionMixLevel(leveldB));
798 }
799
getPlaybackRateParameters(audio_playback_rate_t * playbackRate)800 status_t StreamOutHalHidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
801 TIME_CHECK();
802 if (mStream == 0) return NO_INIT;
803 Result retval;
804 Return<void> ret = mStream->getPlaybackRateParameters(
805 [&](Result r, PlaybackRate hidlPlaybackRate) {
806 retval = r;
807 if (retval == Result::OK) {
808 playbackRate->mSpeed = hidlPlaybackRate.speed;
809 playbackRate->mPitch = hidlPlaybackRate.pitch;
810 playbackRate->mStretchMode =
811 static_cast<audio_timestretch_stretch_mode_t>(
812 hidlPlaybackRate.timestretchMode);
813 playbackRate->mFallbackMode =
814 static_cast<audio_timestretch_fallback_mode_t>(
815 hidlPlaybackRate.fallbackMode);
816 }
817 });
818 return processReturn("getPlaybackRateParameters", ret, retval);
819 }
820
setPlaybackRateParameters(const audio_playback_rate_t & playbackRate)821 status_t StreamOutHalHidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
822 TIME_CHECK();
823 if (mStream == 0) return NO_INIT;
824 return processReturn(
825 "setPlaybackRateParameters", mStream->setPlaybackRateParameters(
826 PlaybackRate{playbackRate.mSpeed, playbackRate.mPitch,
827 static_cast<TimestretchMode>(playbackRate.mStretchMode),
828 static_cast<TimestretchFallbackMode>(playbackRate.mFallbackMode)}));
829 }
830
831 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutEventCallback.h)
832
833 namespace {
834
835 struct StreamOutEventCallback : public IStreamOutEventCallback {
StreamOutEventCallbackandroid::__anon6103522a1311::StreamOutEventCallback836 StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
837
838 // IStreamOutEventCallback implementation
onCodecFormatChangedandroid::__anon6103522a1311::StreamOutEventCallback839 Return<void> onCodecFormatChanged(
840 const android::hardware::hidl_vec<uint8_t>& audioMetadata) override {
841 sp<StreamOutHalHidl> stream = mStream.promote();
842 if (stream != nullptr) {
843 std::basic_string<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
844 stream->onCodecFormatChanged(metadataBs);
845 }
846 return Void();
847 }
848
849 private:
850 wp<StreamOutHalHidl> mStream;
851 };
852
853 } // namespace
854
setEventCallback(const sp<StreamOutHalInterfaceEventCallback> & callback)855 status_t StreamOutHalHidl::setEventCallback(
856 const sp<StreamOutHalInterfaceEventCallback>& callback) {
857 TIME_CHECK();
858 if (mStream == nullptr) return NO_INIT;
859 mEventCallback = callback;
860 status_t status = processReturn(
861 "setEventCallback",
862 mStream->setEventCallback(
863 callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
864 return status;
865 }
866 #endif
867
868 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
869 using hardware::audio::V7_1::LatencyMode;
870
setLatencyMode(audio_latency_mode_t mode)871 status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode) {
872 TIME_CHECK();
873 if (mStream == 0) return NO_INIT;
874 return processReturn(
875 "setLatencyMode", mStream->setLatencyMode(static_cast<LatencyMode>(mode)));
876 };
877
getRecommendedLatencyModes(std::vector<audio_latency_mode_t> * modes)878 status_t StreamOutHalHidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
879 TIME_CHECK();
880 if (!mStream) return NO_INIT;
881 Result retval;
882 Return<void> ret = mStream->getRecommendedLatencyModes(
883 [&](Result r, hidl_vec<LatencyMode> hidlModes) {
884 retval = r;
885 for (size_t i = 0; i < hidlModes.size(); i++) {
886 modes->push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
887 }
888 });
889 return processReturn("getRecommendedLatencyModes", ret, retval);
890 };
891
892 #include PATH(android/hardware/audio/FILE_VERSION/IStreamOutLatencyModeCallback.h)
893
894 using hardware::audio::V7_1::IStreamOutLatencyModeCallback;
895
896 namespace {
897 struct StreamOutLatencyModeCallback : public IStreamOutLatencyModeCallback {
StreamOutLatencyModeCallbackandroid::__anon6103522a1511::StreamOutLatencyModeCallback898 StreamOutLatencyModeCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
899
900 // IStreamOutLatencyModeCallback implementation
onRecommendedLatencyModeChangedandroid::__anon6103522a1511::StreamOutLatencyModeCallback901 Return<void> onRecommendedLatencyModeChanged(const hidl_vec<LatencyMode>& hidlModes) override {
902 sp<StreamOutHalHidl> stream = mStream.promote();
903 if (stream != nullptr) {
904 std::vector<audio_latency_mode_t> modes;
905 for (size_t i = 0; i < hidlModes.size(); i++) {
906 modes.push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
907 }
908 stream->onRecommendedLatencyModeChanged(modes);
909 }
910 return Void();
911 }
912
913 private:
914 wp<StreamOutHalHidl> mStream;
915 };
916 } // namespace
917
setLatencyModeCallback(const sp<StreamOutHalInterfaceLatencyModeCallback> & callback)918 status_t StreamOutHalHidl::setLatencyModeCallback(
919 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
920 TIME_CHECK();
921
922 if (mStream == nullptr) return NO_INIT;
923 mLatencyModeCallback = callback;
924 status_t status = processReturn(
925 "setLatencyModeCallback",
926 mStream->setLatencyModeCallback(
927 callback.get() == nullptr ? nullptr : new StreamOutLatencyModeCallback(this)));
928 return status;
929 };
930
931 #else
932
setLatencyMode(audio_latency_mode_t mode __unused)933 status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode __unused) {
934 return INVALID_OPERATION;
935 };
936
getRecommendedLatencyModes(std::vector<audio_latency_mode_t> * modes __unused)937 status_t StreamOutHalHidl::getRecommendedLatencyModes(
938 std::vector<audio_latency_mode_t> *modes __unused) {
939 return INVALID_OPERATION;
940 };
941
setLatencyModeCallback(const sp<StreamOutHalInterfaceLatencyModeCallback> & callback __unused)942 status_t StreamOutHalHidl::setLatencyModeCallback(
943 const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
944 return INVALID_OPERATION;
945 };
946
947 #endif
948
onWriteReady()949 void StreamOutHalHidl::onWriteReady() {
950 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
951 if (callback == 0) return;
952 ALOGV("asyncCallback onWriteReady");
953 callback->onWriteReady();
954 }
955
onDrainReady()956 void StreamOutHalHidl::onDrainReady() {
957 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
958 if (callback == 0) return;
959 ALOGV("asyncCallback onDrainReady");
960 callback->onDrainReady();
961 }
962
onError()963 void StreamOutHalHidl::onError() {
964 sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
965 if (callback == 0) return;
966 ALOGV("asyncCallback onError");
967 callback->onError();
968 }
969
onCodecFormatChanged(const std::basic_string<uint8_t> & metadataBs)970 void StreamOutHalHidl::onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) {
971 sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
972 if (callback == nullptr) return;
973 ALOGV("asyncCodecFormatCallback %s", __func__);
974 callback->onCodecFormatChanged(metadataBs);
975 }
976
onRecommendedLatencyModeChanged(const std::vector<audio_latency_mode_t> & modes)977 void StreamOutHalHidl::onRecommendedLatencyModeChanged(
978 const std::vector<audio_latency_mode_t>& modes) {
979 sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
980 if (callback == nullptr) return;
981 callback->onRecommendedLatencyModeChanged(modes);
982 }
983
exit()984 status_t StreamOutHalHidl::exit() {
985 // Signal exiting to HALs that use intermediate pipes to close them.
986 AudioParameter param;
987 param.addInt(String8(AudioParameter::keyExiting), 1);
988 param.add(String8(AudioParameter::keyClosing), String8(AudioParameter::valueTrue));
989 return setParameters(param.toString());
990 }
991
StreamInHalHidl(const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> & stream)992 StreamInHalHidl::StreamInHalHidl(
993 const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn>& stream)
994 : StreamHalHidl("StreamInHalHidl", stream.get())
995 , mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
996 }
997
~StreamInHalHidl()998 StreamInHalHidl::~StreamInHalHidl() {
999 if (mStream != 0) {
1000 processReturn("close", mStream->close());
1001 }
1002 if (mEfGroup) {
1003 EventFlag::deleteEventFlag(&mEfGroup);
1004 }
1005 }
1006
getFrameSize(size_t * size)1007 status_t StreamInHalHidl::getFrameSize(size_t *size) {
1008 TIME_CHECK();
1009 if (mStream == 0) return NO_INIT;
1010 return processReturn("getFrameSize", mStream->getFrameSize(), size);
1011 }
1012
setGain(float gain)1013 status_t StreamInHalHidl::setGain(float gain) {
1014 TIME_CHECK();
1015 if (mStream == 0) return NO_INIT;
1016 return processReturn("setGain", mStream->setGain(gain));
1017 }
1018
read(void * buffer,size_t bytes,size_t * read)1019 status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
1020 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
1021 if (mStream == 0) return NO_INIT;
1022 *read = 0;
1023
1024 if (bytes == 0 && !mDataMQ) {
1025 // Can't determine the size for the MQ buffer. Wait for a non-empty read request.
1026 return OK;
1027 }
1028
1029 status_t status;
1030 if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
1031 return status;
1032 }
1033
1034 ReadParameters params;
1035 params.command = ReadCommand::READ;
1036 params.params.read = bytes;
1037 status = callReaderThread(params, "read",
1038 [&](const ReadStatus& readStatus) {
1039 const size_t availToRead = mDataMQ->availableToRead();
1040 if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
1041 ALOGE("data message queue read failed for \"read\"");
1042 }
1043 ALOGW_IF(availToRead != readStatus.reply.read,
1044 "HAL read report inconsistent: mq = %d, status = %d",
1045 (int32_t)availToRead, (int32_t)readStatus.reply.read);
1046 *read = readStatus.reply.read;
1047 });
1048 mStreamPowerLog.log(buffer, *read);
1049 return status;
1050 }
1051
callReaderThread(const ReadParameters & params,const char * cmdName,StreamInHalHidl::ReaderCallback callback)1052 status_t StreamInHalHidl::callReaderThread(
1053 const ReadParameters& params, const char* cmdName,
1054 StreamInHalHidl::ReaderCallback callback) {
1055 if (!mCommandMQ->write(¶ms)) {
1056 ALOGW("command message queue write failed");
1057 return -EAGAIN;
1058 }
1059 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
1060
1061 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
1062 uint32_t efState = 0;
1063 retry:
1064 status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
1065 if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
1066 ReadStatus readStatus;
1067 readStatus.retval = Result::NOT_INITIALIZED;
1068 if (!mStatusMQ->read(&readStatus)) {
1069 ALOGE("status message read failed for \"%s\"", cmdName);
1070 }
1071 if (readStatus.retval == Result::OK) {
1072 ret = OK;
1073 callback(readStatus);
1074 } else {
1075 ret = processReturn(cmdName, readStatus.retval);
1076 }
1077 return ret;
1078 }
1079 if (ret == -EAGAIN || ret == -EINTR) {
1080 // Spurious wakeup. This normally retries no more than once.
1081 goto retry;
1082 }
1083 return ret;
1084 }
1085
prepareForReading(size_t bufferSize)1086 status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
1087 std::unique_ptr<CommandMQ> tempCommandMQ;
1088 std::unique_ptr<DataMQ> tempDataMQ;
1089 std::unique_ptr<StatusMQ> tempStatusMQ;
1090 Result retval;
1091 pid_t halThreadPid, halThreadTid;
1092 Return<void> ret = mStream->prepareForReading(
1093 1, bufferSize,
1094 [&](Result r,
1095 const CommandMQ::Descriptor& commandMQ,
1096 const DataMQ::Descriptor& dataMQ,
1097 const StatusMQ::Descriptor& statusMQ,
1098 const auto& halThreadInfo) {
1099 retval = r;
1100 if (retval == Result::OK) {
1101 tempCommandMQ.reset(new CommandMQ(commandMQ));
1102 tempDataMQ.reset(new DataMQ(dataMQ));
1103 tempStatusMQ.reset(new StatusMQ(statusMQ));
1104 if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
1105 EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
1106 }
1107 #if MAJOR_VERSION <= 6
1108 halThreadPid = halThreadInfo.pid;
1109 halThreadTid = halThreadInfo.tid;
1110 #else
1111 halThreadTid = halThreadInfo;
1112 #endif
1113 }
1114 });
1115 if (!ret.isOk() || retval != Result::OK) {
1116 return processReturn("prepareForReading", ret, retval);
1117 }
1118 if (!tempCommandMQ || !tempCommandMQ->isValid() ||
1119 !tempDataMQ || !tempDataMQ->isValid() ||
1120 !tempStatusMQ || !tempStatusMQ->isValid() ||
1121 !mEfGroup) {
1122 ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
1123 ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
1124 "Command message queue for writing is invalid");
1125 ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
1126 ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
1127 ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
1128 ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
1129 "Status message queue for reading is invalid");
1130 ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
1131 return NO_INIT;
1132 }
1133 #if MAJOR_VERSION >= 7
1134 if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
1135 return status;
1136 }
1137 #endif
1138 requestHalThreadPriority(halThreadPid, halThreadTid);
1139
1140 mCommandMQ = std::move(tempCommandMQ);
1141 mDataMQ = std::move(tempDataMQ);
1142 mStatusMQ = std::move(tempStatusMQ);
1143 mReaderClient = gettid();
1144 return OK;
1145 }
1146
getInputFramesLost(uint32_t * framesLost)1147 status_t StreamInHalHidl::getInputFramesLost(uint32_t *framesLost) {
1148 TIME_CHECK();
1149 if (mStream == 0) return NO_INIT;
1150 return processReturn("getInputFramesLost", mStream->getInputFramesLost(), framesLost);
1151 }
1152
getCapturePosition(int64_t * frames,int64_t * time)1153 status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
1154 // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
1155 if (mStream == 0) return NO_INIT;
1156 if (mReaderClient == gettid() && mCommandMQ) {
1157 ReadParameters params;
1158 params.command = ReadCommand::GET_CAPTURE_POSITION;
1159 return callReaderThread(params, "getCapturePosition",
1160 [&](const ReadStatus& readStatus) {
1161 *frames = readStatus.reply.capturePosition.frames;
1162 *time = readStatus.reply.capturePosition.time;
1163 });
1164 } else {
1165 Result retval;
1166 Return<void> ret = mStream->getCapturePosition(
1167 [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
1168 retval = r;
1169 if (retval == Result::OK) {
1170 *frames = hidlFrames;
1171 *time = hidlTime;
1172 }
1173 });
1174 return processReturn("getCapturePosition", ret, retval);
1175 }
1176 }
1177
1178 #if MAJOR_VERSION == 2
getActiveMicrophones(std::vector<media::MicrophoneInfoFw> * microphones __unused)1179 status_t StreamInHalHidl::getActiveMicrophones(
1180 std::vector<media::MicrophoneInfoFw> *microphones __unused) {
1181 if (mStream == 0) return NO_INIT;
1182 return INVALID_OPERATION;
1183 }
1184
updateSinkMetadata(const StreamInHalInterface::SinkMetadata &)1185 status_t StreamInHalHidl::updateSinkMetadata(
1186 const StreamInHalInterface::SinkMetadata& /* sinkMetadata */) {
1187 // Audio HAL V2.0 does not support propagating sink metadata
1188 return INVALID_OPERATION;
1189 }
1190
1191 #elif MAJOR_VERSION >= 4
getActiveMicrophones(std::vector<media::MicrophoneInfoFw> * microphonesInfo)1192 status_t StreamInHalHidl::getActiveMicrophones(
1193 std::vector<media::MicrophoneInfoFw> *microphonesInfo) {
1194 TIME_CHECK();
1195 if (!mStream) return NO_INIT;
1196 Result retval;
1197 Return<void> ret = mStream->getActiveMicrophones(
1198 [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
1199 retval = r;
1200 for (size_t k = 0; k < micArrayHal.size(); k++) {
1201 // Convert via legacy.
1202 audio_microphone_characteristic_t dst;
1203 (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
1204 auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(dst);
1205 if (conv.ok()) {
1206 microphonesInfo->push_back(conv.value());
1207 } else {
1208 ALOGW("getActiveMicrophones: could not convert %s to AIDL: %d",
1209 toString(micArrayHal[k]).c_str(), conv.error());
1210 microphonesInfo->push_back(media::MicrophoneInfoFw{});
1211 }
1212 }
1213 });
1214 return processReturn("getActiveMicrophones", ret, retval);
1215 }
1216
updateSinkMetadata(const StreamInHalInterface::SinkMetadata & sinkMetadata)1217 status_t StreamInHalHidl::updateSinkMetadata(const
1218 StreamInHalInterface::SinkMetadata& sinkMetadata) {
1219 TIME_CHECK();
1220 #if MAJOR_VERSION == 4
1221 ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1222 #else
1223 ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1224 #endif
1225 if (status_t status = CoreUtils::sinkMetadataFromHalV7(
1226 sinkMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
1227 status != OK) {
1228 return status;
1229 }
1230 return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(hidlMetadata));
1231 }
1232 #endif
1233
1234 #if MAJOR_VERSION < 5
setPreferredMicrophoneDirection(audio_microphone_direction_t direction __unused)1235 status_t StreamInHalHidl::setPreferredMicrophoneDirection(
1236 audio_microphone_direction_t direction __unused) {
1237 if (mStream == 0) return NO_INIT;
1238 return INVALID_OPERATION;
1239 }
1240
setPreferredMicrophoneFieldDimension(float zoom __unused)1241 status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
1242 if (mStream == 0) return NO_INIT;
1243 return INVALID_OPERATION;
1244 }
1245 #else
setPreferredMicrophoneDirection(audio_microphone_direction_t direction)1246 status_t StreamInHalHidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
1247 TIME_CHECK();
1248 if (!mStream) return NO_INIT;
1249 return processReturn("setPreferredMicrophoneDirection",
1250 mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
1251 }
1252
setPreferredMicrophoneFieldDimension(float zoom)1253 status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom) {
1254 TIME_CHECK();
1255 if (!mStream) return NO_INIT;
1256 return processReturn("setPreferredMicrophoneFieldDimension",
1257 mStream->setMicrophoneFieldDimension(zoom));
1258 }
1259 #endif
1260
1261 } // namespace android
1262