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