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