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