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