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