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