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