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