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