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