1 /*
2  * Copyright (C) 2023 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 "StreamHalAidl"
18 //#define LOG_NDEBUG 0
19 
20 #include <algorithm>
21 #include <cstdint>
22 
23 #include <audio_utils/clock.h>
24 #include <media/AidlConversion.h>
25 #include <media/AidlConversionCore.h>
26 #include <media/AidlConversionCppNdk.h>
27 #include <media/AidlConversionNdk.h>
28 #include <media/AidlConversionUtil.h>
29 #include <media/AudioParameter.h>
30 #include <mediautils/TimeCheck.h>
31 #include <system/audio.h>
32 #include <Utils.h>
33 #include <utils/Log.h>
34 
35 #include "DeviceHalAidl.h"
36 #include "EffectHalAidl.h"
37 #include "StreamHalAidl.h"
38 
39 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
40 using ::aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
41 using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata;
42 using ::aidl::android::hardware::audio::common::RecordTrackMetadata;
43 using ::aidl::android::hardware::audio::core::IStreamCommon;
44 using ::aidl::android::hardware::audio::core::IStreamIn;
45 using ::aidl::android::hardware::audio::core::IStreamOut;
46 using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
47 using ::aidl::android::hardware::audio::core::StreamDescriptor;
48 using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
49 using ::aidl::android::media::audio::IHalAdapterVendorExtension;
50 
51 namespace android {
52 
53 using HalCommand = StreamDescriptor::Command;
54 namespace {
makeHalCommand()55 template<HalCommand::Tag cmd> HalCommand makeHalCommand() {
56     return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{});
57 }
makeHalCommand(T data)58 template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
59     return HalCommand::make<cmd>(data);
60 }
61 }  // namespace
62 
63 // static
64 template<class T>
getStreamCommon(const std::shared_ptr<T> & stream)65 std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
66     std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> streamCommon;
67     if (stream != nullptr) {
68         if (ndk::ScopedAStatus status = stream->getStreamCommon(&streamCommon);
69                 !status.isOk()) {
70             ALOGE("%s: failed to retrieve IStreamCommon instance: %s", __func__,
71                     status.getDescription().c_str());
72         }
73     }
74     return streamCommon;
75 }
76 
StreamHalAidl(std::string_view className,bool isInput,const audio_config & config,int32_t nominalLatency,StreamContextAidl && context,const std::shared_ptr<IStreamCommon> & stream,const std::shared_ptr<IHalAdapterVendorExtension> & vext)77 StreamHalAidl::StreamHalAidl(
78         std::string_view className, bool isInput, const audio_config& config,
79         int32_t nominalLatency, StreamContextAidl&& context,
80         const std::shared_ptr<IStreamCommon>& stream,
81         const std::shared_ptr<IHalAdapterVendorExtension>& vext)
82         : ConversionHelperAidl(className),
83           mIsInput(isInput),
84           mConfig(configToBase(config)),
85           mContext(std::move(context)),
86           mStream(stream),
87           mVendorExt(vext),
88           mLastReplyLifeTimeNs(
89                   std::min(static_cast<size_t>(100),
90                           2 * mContext.getBufferDurationMs(mConfig.sample_rate))
91                   * NANOS_PER_MILLISECOND)
92 {
93     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
94     {
95         std::lock_guard l(mLock);
96         mLastReply.latencyMs = nominalLatency;
97     }
98     // Instrument audio signal power logging.
99     // Note: This assumes channel mask, format, and sample rate do not change after creation.
100     if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
101             /* mStreamPowerLog.isUserDebugOrEngBuild() && */
102             StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
103         mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
104     }
105 }
106 
~StreamHalAidl()107 StreamHalAidl::~StreamHalAidl() {
108     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
109     if (mStream != nullptr) {
110         ndk::ScopedAStatus status = mStream->close();
111         ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
112     }
113 }
114 
getBufferSize(size_t * size)115 status_t StreamHalAidl::getBufferSize(size_t *size) {
116     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
117     if (size == nullptr) {
118         return BAD_VALUE;
119     }
120     if (mContext.getFrameSizeBytes() == 0 || mContext.getBufferSizeFrames() == 0 ||
121             !mStream) {
122         return NO_INIT;
123     }
124     *size = mContext.getBufferSizeBytes();
125     return OK;
126 }
127 
getAudioProperties(audio_config_base_t * configBase)128 status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
129     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
130     if (configBase == nullptr) {
131         return BAD_VALUE;
132     }
133     if (!mStream) return NO_INIT;
134     *configBase = mConfig;
135     return OK;
136 }
137 
setParameters(const String8 & kvPairs)138 status_t StreamHalAidl::setParameters(const String8& kvPairs) {
139     TIME_CHECK();
140     if (!mStream) return NO_INIT;
141     AudioParameter parameters(kvPairs);
142     ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
143 
144     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
145                     parameters, String8(AudioParameter::keyStreamHwAvSync),
146             [&](int hwAvSyncId) {
147                 return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
148             }));
149     return parseAndSetVendorParameters(mVendorExt, mStream, parameters);
150 }
151 
getParameters(const String8 & keys __unused,String8 * values)152 status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
153     TIME_CHECK();
154     if (!mStream) return NO_INIT;
155     if (values == nullptr) {
156         return BAD_VALUE;
157     }
158     AudioParameter parameterKeys(keys), result;
159     *values = result.toString();
160     return parseAndGetVendorParameters(mVendorExt, mStream, parameterKeys, values);
161 }
162 
getFrameSize(size_t * size)163 status_t StreamHalAidl::getFrameSize(size_t *size) {
164     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
165     if (size == nullptr) {
166         return BAD_VALUE;
167     }
168     if (mContext.getFrameSizeBytes() == 0 || !mStream) {
169         return NO_INIT;
170     }
171     *size = mContext.getFrameSizeBytes();
172     return OK;
173 }
174 
addEffect(sp<EffectHalInterface> effect)175 status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect) {
176     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
177     TIME_CHECK();
178     if (!mStream) return NO_INIT;
179     if (effect == nullptr) {
180         return BAD_VALUE;
181     }
182     auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
183     return statusTFromBinderStatus(mStream->addEffect(aidlEffect->getIEffect()));
184 }
185 
removeEffect(sp<EffectHalInterface> effect)186 status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect) {
187     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
188     TIME_CHECK();
189     if (!mStream) return NO_INIT;
190     if (effect == nullptr) {
191         return BAD_VALUE;
192     }
193     auto aidlEffect = sp<effect::EffectHalAidl>::cast(effect);
194     return statusTFromBinderStatus(mStream->removeEffect(aidlEffect->getIEffect()));
195 }
196 
standby()197 status_t StreamHalAidl::standby() {
198     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
199     TIME_CHECK();
200     if (!mStream) return NO_INIT;
201     const auto state = getState();
202     StreamDescriptor::Reply reply;
203     switch (state) {
204         case StreamDescriptor::State::ACTIVE:
205         case StreamDescriptor::State::DRAINING:
206         case StreamDescriptor::State::TRANSFERRING:
207             RETURN_STATUS_IF_ERROR(pause(&reply));
208             if (reply.state != StreamDescriptor::State::PAUSED &&
209                     reply.state != StreamDescriptor::State::DRAIN_PAUSED &&
210                     reply.state != StreamDescriptor::State::TRANSFER_PAUSED) {
211                 ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
212                         __func__, toString(reply.state).c_str());
213                 return INVALID_OPERATION;
214             }
215             FALLTHROUGH_INTENDED;
216         case StreamDescriptor::State::PAUSED:
217         case StreamDescriptor::State::DRAIN_PAUSED:
218         case StreamDescriptor::State::TRANSFER_PAUSED:
219             if (mIsInput) return flush();
220             RETURN_STATUS_IF_ERROR(flush(&reply));
221             if (reply.state != StreamDescriptor::State::IDLE) {
222                 ALOGE("%s: unexpected stream state: %s (expected IDLE)",
223                         __func__, toString(reply.state).c_str());
224                 return INVALID_OPERATION;
225             }
226             FALLTHROUGH_INTENDED;
227         case StreamDescriptor::State::IDLE:
228             RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
229                             &reply, true /*safeFromNonWorkerThread*/));
230             if (reply.state != StreamDescriptor::State::STANDBY) {
231                 ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
232                         __func__, toString(reply.state).c_str());
233                 return INVALID_OPERATION;
234             }
235             FALLTHROUGH_INTENDED;
236         case StreamDescriptor::State::STANDBY:
237             return OK;
238         default:
239             ALOGE("%s: not supported from %s stream state %s",
240                     __func__, mIsInput ? "input" : "output", toString(state).c_str());
241             return INVALID_OPERATION;
242     }
243 }
244 
dump(int fd,const Vector<String16> & args)245 status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
246     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
247     TIME_CHECK();
248     if (!mStream) return NO_INIT;
249     Vector<String16> newArgs = args;
250     newArgs.push(String16(kDumpFromAudioServerArgument));
251     status_t status = mStream->dump(fd, Args(newArgs).args(), newArgs.size());
252     mStreamPowerLog.dump(fd);
253     return status;
254 }
255 
start()256 status_t StreamHalAidl::start() {
257     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
258     TIME_CHECK();
259     if (!mStream) return NO_INIT;
260     if (!mContext.isMmapped()) {
261         return BAD_VALUE;
262     }
263     StreamDescriptor::Reply reply;
264     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
265     switch (reply.state) {
266         case StreamDescriptor::State::STANDBY:
267             RETURN_STATUS_IF_ERROR(
268                     sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true));
269             if (reply.state != StreamDescriptor::State::IDLE) {
270                 ALOGE("%s: unexpected stream state: %s (expected IDLE)",
271                         __func__, toString(reply.state).c_str());
272                 return INVALID_OPERATION;
273             }
274             FALLTHROUGH_INTENDED;
275         case StreamDescriptor::State::IDLE:
276             RETURN_STATUS_IF_ERROR(
277                     sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true));
278             if (reply.state != StreamDescriptor::State::ACTIVE) {
279                 ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
280                         __func__, toString(reply.state).c_str());
281                 return INVALID_OPERATION;
282             }
283             FALLTHROUGH_INTENDED;
284         case StreamDescriptor::State::ACTIVE:
285             return OK;
286         case StreamDescriptor::State::DRAINING:
287             RETURN_STATUS_IF_ERROR(
288                     sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true));
289             if (reply.state != StreamDescriptor::State::ACTIVE) {
290                 ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
291                         __func__, toString(reply.state).c_str());
292                 return INVALID_OPERATION;
293             }
294             return OK;
295         default:
296             ALOGE("%s: not supported from %s stream state %s",
297                     __func__, mIsInput ? "input" : "output", toString(reply.state).c_str());
298             return INVALID_OPERATION;
299     }
300 }
301 
stop()302 status_t StreamHalAidl::stop() {
303     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
304     TIME_CHECK();
305     if (!mStream) return NO_INIT;
306     if (!mContext.isMmapped()) {
307         return BAD_VALUE;
308     }
309     StreamDescriptor::Reply reply;
310     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
311     if (const auto state = reply.state; state == StreamDescriptor::State::ACTIVE) {
312         return drain(false /*earlyNotify*/, nullptr);
313     } else if (state == StreamDescriptor::State::DRAINING) {
314         RETURN_STATUS_IF_ERROR(pause());
315         return flush();
316     } else if (state == StreamDescriptor::State::PAUSED) {
317         return flush();
318     } else if (state != StreamDescriptor::State::IDLE &&
319             state != StreamDescriptor::State::STANDBY) {
320         ALOGE("%s: not supported from %s stream state %s",
321                 __func__, mIsInput ? "input" : "output", toString(state).c_str());
322         return INVALID_OPERATION;
323     }
324     return OK;
325 }
326 
getLatency(uint32_t * latency)327 status_t StreamHalAidl::getLatency(uint32_t *latency) {
328     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
329     if (!mStream) return NO_INIT;
330     StreamDescriptor::Reply reply;
331     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
332     *latency = std::clamp(std::max<int32_t>(0, reply.latencyMs), 1, 3000);
333     ALOGW_IF(reply.latencyMs != static_cast<int32_t>(*latency),
334              "Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
335              *latency);
336     return OK;
337 }
338 
getObservablePosition(int64_t * frames,int64_t * timestamp,StatePositions * statePositions)339 status_t StreamHalAidl::getObservablePosition(int64_t* frames, int64_t* timestamp,
340         StatePositions* statePositions) {
341     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
342     if (!mStream) return NO_INIT;
343     StreamDescriptor::Reply reply;
344     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, statePositions));
345     *frames = std::max<int64_t>(0, reply.observable.frames);
346     *timestamp = std::max<int64_t>(0, reply.observable.timeNs);
347     return OK;
348 }
349 
getHardwarePosition(int64_t * frames,int64_t * timestamp)350 status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
351     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
352     if (!mStream) return NO_INIT;
353     StreamDescriptor::Reply reply;
354     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
355     *frames = std::max<int64_t>(0, reply.hardware.frames);
356     *timestamp = std::max<int64_t>(0, reply.hardware.timeNs);
357     return OK;
358 }
359 
getXruns(int32_t * frames)360 status_t StreamHalAidl::getXruns(int32_t *frames) {
361     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
362     if (!mStream) return NO_INIT;
363     StreamDescriptor::Reply reply;
364     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
365     *frames = std::max<int32_t>(0, reply.xrunFrames);
366     return OK;
367 }
368 
transfer(void * buffer,size_t bytes,size_t * transferred)369 status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
370     ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
371     // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
372     if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
373     mWorkerTid.store(gettid(), std::memory_order_release);
374     // Switch the stream into an active state if needed.
375     // Note: in future we may add support for priming the audio pipeline
376     // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
377     // stream state), however this scenario wasn't supported by the HIDL HAL.
378     if (getState() == StreamDescriptor::State::STANDBY) {
379         StreamDescriptor::Reply reply;
380         RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply));
381         if (reply.state != StreamDescriptor::State::IDLE) {
382             ALOGE("%s: failed to get the stream out of standby, actual state: %s",
383                     __func__, toString(reply.state).c_str());
384             return INVALID_OPERATION;
385         }
386     }
387     StreamContextAidl::DataMQ::Error fmqError = StreamContextAidl::DataMQ::Error::NONE;
388     std::string fmqErrorMsg;
389     if (!mIsInput) {
390         bytes = std::min(bytes,
391                 mContext.getDataMQ()->availableToWrite(&fmqError, &fmqErrorMsg));
392     }
393     StreamDescriptor::Command burst =
394             StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
395     if (!mIsInput) {
396         if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
397             ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
398             return NOT_ENOUGH_DATA;
399         }
400     }
401     StreamDescriptor::Reply reply;
402     RETURN_STATUS_IF_ERROR(sendCommand(burst, &reply));
403     *transferred = reply.fmqByteCount;
404     if (mIsInput) {
405         LOG_ALWAYS_FATAL_IF(*transferred > bytes,
406                 "%s: HAL module read %zu bytes, which exceeds requested count %zu",
407                 __func__, *transferred, bytes);
408         if (auto toRead = mContext.getDataMQ()->availableToRead(&fmqError, &fmqErrorMsg);
409                 toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
410             ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
411             return NOT_ENOUGH_DATA;
412         }
413     }
414     LOG_ALWAYS_FATAL_IF(fmqError != StreamContextAidl::DataMQ::Error::NONE,
415             "%s", fmqErrorMsg.c_str());
416     mStreamPowerLog.log(buffer, *transferred);
417     return OK;
418 }
419 
pause(StreamDescriptor::Reply * reply)420 status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
421     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
422     TIME_CHECK();
423     if (!mStream) return NO_INIT;
424     return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
425             true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
426 }
427 
resume(StreamDescriptor::Reply * reply)428 status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
429     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
430     TIME_CHECK();
431     if (!mStream) return NO_INIT;
432     if (mIsInput) {
433         return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
434     } else {
435         if (const auto state = getState(); state == StreamDescriptor::State::IDLE) {
436             // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
437             // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
438             StreamDescriptor::Reply localReply{};
439             StreamDescriptor::Reply* innerReply = reply ?: &localReply;
440             RETURN_STATUS_IF_ERROR(
441                     sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply));
442             if (innerReply->state != StreamDescriptor::State::ACTIVE) {
443                 ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
444                         __func__, toString(innerReply->state).c_str());
445                 return INVALID_OPERATION;
446             }
447             return OK;
448         } else if (state == StreamDescriptor::State::PAUSED ||
449                    state == StreamDescriptor::State::TRANSFER_PAUSED ||
450                    state == StreamDescriptor::State::DRAIN_PAUSED) {
451             return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
452         } else {
453             ALOGE("%s: unexpected stream state: %s (expected IDLE or one of *PAUSED states)",
454                         __func__, toString(state).c_str());
455             return INVALID_OPERATION;
456         }
457     }
458 }
459 
drain(bool earlyNotify,StreamDescriptor::Reply * reply)460 status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
461     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
462     TIME_CHECK();
463     if (!mStream) return NO_INIT;
464     return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
465                     mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
466                     earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
467                     StreamDescriptor::DrainMode::DRAIN_ALL), reply,
468                     true /*safeFromNonWorkerThread*/);
469 }
470 
flush(StreamDescriptor::Reply * reply)471 status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
472     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
473     TIME_CHECK();
474     if (!mStream) return NO_INIT;
475     return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
476             true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
477 }
478 
exit()479 status_t StreamHalAidl::exit() {
480     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
481     TIME_CHECK();
482     if (!mStream) return NO_INIT;
483     return statusTFromBinderStatus(mStream->prepareToClose());
484 }
485 
onAsyncTransferReady()486 void StreamHalAidl::onAsyncTransferReady() {
487     if (auto state = getState(); state == StreamDescriptor::State::TRANSFERRING) {
488         // Retrieve the current state together with position counters unconditionally
489         // to ensure that the state on our side gets updated.
490         sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
491                 nullptr, true /*safeFromNonWorkerThread */);
492     } else {
493         ALOGW("%s: unexpected onTransferReady in the state %s", __func__, toString(state).c_str());
494     }
495 }
496 
onAsyncDrainReady()497 void StreamHalAidl::onAsyncDrainReady() {
498     if (auto state = getState(); state == StreamDescriptor::State::DRAINING) {
499         // Retrieve the current state together with position counters unconditionally
500         // to ensure that the state on our side gets updated.
501         sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), nullptr,
502                     true /*safeFromNonWorkerThread */);
503         // For compatibility with HIDL behavior, apply a "soft" position reset
504         // after receiving the "drain ready" callback.
505         std::lock_guard l(mLock);
506         mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames;
507     } else {
508         ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str());
509     }
510 }
511 
onAsyncError()512 void StreamHalAidl::onAsyncError() {
513     std::lock_guard l(mLock);
514     ALOGW("%s: received in the state %s", __func__, toString(mLastReply.state).c_str());
515     mLastReply.state = StreamDescriptor::State::ERROR;
516 }
517 
createMmapBuffer(int32_t minSizeFrames __unused,struct audio_mmap_buffer_info * info)518 status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
519                                          struct audio_mmap_buffer_info *info) {
520     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
521     TIME_CHECK();
522     if (!mStream) return NO_INIT;
523     if (!mContext.isMmapped()) {
524         return BAD_VALUE;
525     }
526     const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor();
527     info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get();
528     info->buffer_size_frames = mContext.getBufferSizeFrames();
529     info->burst_size_frames = bufferDescriptor.burstSizeFrames;
530     info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags);
531 
532     return OK;
533 }
534 
getMmapPosition(struct audio_mmap_position * position)535 status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position) {
536     TIME_CHECK();
537     if (!mStream) return NO_INIT;
538     if (!mContext.isMmapped()) {
539         return BAD_VALUE;
540     }
541     int64_t aidlPosition = 0, aidlTimestamp = 0;
542     RETURN_STATUS_IF_ERROR(getHardwarePosition(&aidlPosition, &aidlTimestamp));
543     position->time_nanoseconds = aidlTimestamp;
544     position->position_frames = static_cast<int32_t>(aidlPosition);
545     return OK;
546 }
547 
setHalThreadPriority(int priority __unused)548 status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
549     // Obsolete, must be done by the HAL module.
550     return OK;
551 }
552 
legacyCreateAudioPatch(const struct audio_port_config & port __unused,std::optional<audio_source_t> source __unused,audio_devices_t type __unused)553 status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
554                                                std::optional<audio_source_t> source __unused,
555                                                audio_devices_t type __unused) {
556     // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
557     return INVALID_OPERATION;
558 }
559 
legacyReleaseAudioPatch()560 status_t StreamHalAidl::legacyReleaseAudioPatch() {
561     // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
562     return INVALID_OPERATION;
563 }
564 
sendCommand(const::aidl::android::hardware::audio::core::StreamDescriptor::Command & command,::aidl::android::hardware::audio::core::StreamDescriptor::Reply * reply,bool safeFromNonWorkerThread,StatePositions * statePositions)565 status_t StreamHalAidl::sendCommand(
566         const ::aidl::android::hardware::audio::core::StreamDescriptor::Command& command,
567         ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
568         bool safeFromNonWorkerThread, StatePositions* statePositions) {
569     // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
570     if (!safeFromNonWorkerThread) {
571         const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
572         LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
573                 "%s %s: must be invoked from the worker thread (%d)",
574                 __func__, command.toString().c_str(), workerTid);
575     }
576     StreamDescriptor::Reply localReply{};
577     {
578         std::lock_guard l(mCommandReplyLock);
579         if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
580             ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
581             return NOT_ENOUGH_DATA;
582         }
583         if (reply == nullptr) {
584             reply = &localReply;
585         }
586         if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
587             ALOGE("%s: failed to read from reply MQ, command %s",
588                     __func__, command.toString().c_str());
589             return NOT_ENOUGH_DATA;
590         }
591         {
592             std::lock_guard l(mLock);
593             // Not every command replies with 'latencyMs' field filled out, substitute the last
594             // returned value in that case.
595             if (reply->latencyMs <= 0) {
596                 reply->latencyMs = mLastReply.latencyMs;
597             }
598             mLastReply = *reply;
599             mLastReplyExpirationNs = uptimeNanos() + mLastReplyLifeTimeNs;
600             if (!mIsInput && reply->status == STATUS_OK) {
601                 if (command.getTag() == StreamDescriptor::Command::standby &&
602                         reply->state == StreamDescriptor::State::STANDBY) {
603                     mStatePositions.framesAtStandby = reply->observable.frames;
604                 } else if (command.getTag() == StreamDescriptor::Command::flush &&
605                            reply->state == StreamDescriptor::State::IDLE) {
606                     mStatePositions.framesAtFlushOrDrain = reply->observable.frames;
607                 } else if (!mContext.isAsynchronous() &&
608                         command.getTag() == StreamDescriptor::Command::drain &&
609                         (reply->state == StreamDescriptor::State::IDLE ||
610                                 reply->state == StreamDescriptor::State::DRAINING)) {
611                     mStatePositions.framesAtFlushOrDrain = reply->observable.frames;
612                 } // for asynchronous drain, the frame count is saved in 'onAsyncDrainReady'
613             }
614             if (statePositions != nullptr) {
615                 *statePositions = mStatePositions;
616             }
617         }
618     }
619     switch (reply->status) {
620         case STATUS_OK: return OK;
621         case STATUS_BAD_VALUE: return BAD_VALUE;
622         case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
623         case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
624         default:
625             ALOGE("%s: unexpected status %d returned for command %s",
626                     __func__, reply->status, command.toString().c_str());
627             return INVALID_OPERATION;
628     }
629 }
630 
updateCountersIfNeeded(::aidl::android::hardware::audio::core::StreamDescriptor::Reply * reply,StatePositions * statePositions)631 status_t StreamHalAidl::updateCountersIfNeeded(
632         ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
633         StatePositions* statePositions) {
634     bool doUpdate = false;
635     {
636         std::lock_guard l(mLock);
637         doUpdate = uptimeNanos() > mLastReplyExpirationNs;
638     }
639     if (doUpdate) {
640         // Since updates are paced, it is OK to perform them from any thread, they should
641         // not interfere with I/O operations of the worker.
642         return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
643                 reply, true /*safeFromNonWorkerThread */, statePositions);
644     } else if (reply != nullptr) {  // provide cached reply
645         std::lock_guard l(mLock);
646         *reply = mLastReply;
647         if (statePositions != nullptr) {
648             *statePositions = mStatePositions;
649         }
650     }
651     return OK;
652 }
653 
654 // static
655 ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata & legacy)656 StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
657     ::aidl::android::hardware::audio::common::SourceMetadata aidl;
658     aidl.tracks = VALUE_OR_RETURN(
659             ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
660                     legacy.tracks,
661                     ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
662     return aidl;
663 }
664 
StreamOutHalAidl(const audio_config & config,StreamContextAidl && context,int32_t nominalLatency,const std::shared_ptr<IStreamOut> & stream,const std::shared_ptr<IHalAdapterVendorExtension> & vext,const sp<CallbackBroker> & callbackBroker)665 StreamOutHalAidl::StreamOutHalAidl(
666         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
667         const std::shared_ptr<IStreamOut>& stream,
668         const std::shared_ptr<IHalAdapterVendorExtension>& vext,
669         const sp<CallbackBroker>& callbackBroker)
670         : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
671                 std::move(context), getStreamCommon(stream), vext),
672           mStream(stream), mCallbackBroker(callbackBroker) {
673     // Initialize the offload metadata
674     mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
675     mOffloadMetadata.channelMask = VALUE_OR_FATAL(
676             ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
677                     config.channel_mask, false));
678     mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
679 }
680 
~StreamOutHalAidl()681 StreamOutHalAidl::~StreamOutHalAidl() {
682     if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
683         broker->clearCallbacks(static_cast<StreamOutHalInterface*>(this));
684     }
685 }
686 
setParameters(const String8 & kvPairs)687 status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
688     if (!mStream) return NO_INIT;
689 
690     AudioParameter parameters(kvPairs);
691     ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
692 
693     if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
694         ALOGW("%s: filtering or updating offload metadata failed: %d", __func__, status);
695     }
696 
697     return StreamHalAidl::setParameters(parameters.toString());
698 }
699 
getLatency(uint32_t * latency)700 status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
701     return StreamHalAidl::getLatency(latency);
702 }
703 
setVolume(float left,float right)704 status_t StreamOutHalAidl::setVolume(float left, float right) {
705     TIME_CHECK();
706     if (!mStream) return NO_INIT;
707     size_t channelCount = audio_channel_count_from_out_mask(mConfig.channel_mask);
708     if (channelCount == 0) channelCount = 2;
709     std::vector<float> volumes(channelCount);
710     if (channelCount == 1) {
711         volumes[0] = (left + right) / 2;
712     } else {
713         volumes[0] = left;
714         volumes[1] = right;
715         for (size_t i = 2; i < channelCount; ++i) {
716             volumes[i] = (left + right) / 2;
717         }
718     }
719     return statusTFromBinderStatus(mStream->setHwVolume(volumes));
720 }
721 
selectPresentation(int presentationId,int programId)722 status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
723     TIME_CHECK();
724     if (!mStream) return NO_INIT;
725     return statusTFromBinderStatus(mStream->selectPresentation(presentationId, programId));
726 }
727 
write(const void * buffer,size_t bytes,size_t * written)728 status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
729     if (buffer == nullptr || written == nullptr) {
730         return BAD_VALUE;
731     }
732     // For the output scenario, 'transfer' does not modify the buffer.
733     return transfer(const_cast<void*>(buffer), bytes, written);
734 }
735 
getRenderPosition(uint64_t * dspFrames)736 status_t StreamOutHalAidl::getRenderPosition(uint64_t *dspFrames) {
737     if (dspFrames == nullptr) {
738         return BAD_VALUE;
739     }
740     int64_t aidlFrames = 0, aidlTimestamp = 0;
741     StatePositions statePositions{};
742     RETURN_STATUS_IF_ERROR(
743             getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions));
744     // Number of audio frames since the stream has exited standby.
745     // See the table at the start of 'StreamHalInterface' on when it needs to reset.
746     int64_t mostRecentResetPoint;
747     if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) {
748         mostRecentResetPoint = statePositions.framesAtStandby;
749     } else {
750         mostRecentResetPoint =
751                 std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain);
752     }
753     *dspFrames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint;
754     return OK;
755 }
756 
setCallback(wp<StreamOutHalInterfaceCallback> callback)757 status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
758     ALOGD("%p %s", this, __func__);
759     TIME_CHECK();
760     if (!mStream) return NO_INIT;
761     if (!mContext.isAsynchronous()) {
762         ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
763         return INVALID_OPERATION;
764     }
765     mClientCallback = callback;
766     return OK;
767 }
768 
supportsPauseAndResume(bool * supportsPause,bool * supportsResume)769 status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
770     if (supportsPause == nullptr || supportsResume == nullptr) {
771         return BAD_VALUE;
772     }
773     TIME_CHECK();
774     if (!mStream) return NO_INIT;
775     *supportsPause = *supportsResume = true;
776     return OK;
777 }
778 
pause()779 status_t StreamOutHalAidl::pause() {
780     return StreamHalAidl::pause();
781 }
782 
resume()783 status_t StreamOutHalAidl::resume() {
784     return StreamHalAidl::resume();
785 }
786 
supportsDrain(bool * supportsDrain)787 status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
788     if (supportsDrain == nullptr) {
789         return BAD_VALUE;
790     }
791     TIME_CHECK();
792     if (!mStream) return NO_INIT;
793     *supportsDrain = true;
794     return OK;
795 }
796 
drain(bool earlyNotify)797 status_t StreamOutHalAidl::drain(bool earlyNotify) {
798     return StreamHalAidl::drain(earlyNotify);
799 }
800 
flush()801 status_t StreamOutHalAidl::flush() {
802     return StreamHalAidl::flush();
803 }
804 
getPresentationPosition(uint64_t * frames,struct timespec * timestamp)805 status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
806     if (frames == nullptr || timestamp == nullptr) {
807         return BAD_VALUE;
808     }
809     int64_t aidlFrames = 0, aidlTimestamp = 0;
810     StatePositions statePositions{};
811     RETURN_STATUS_IF_ERROR(getObservablePosition(&aidlFrames, &aidlTimestamp, &statePositions));
812     // See the table at the start of 'StreamHalInterface'.
813     if (!mContext.isAsynchronous() && audio_has_proportional_frames(mConfig.format)) {
814         *frames = aidlFrames;
815     } else {
816         const int64_t mostRecentResetPoint =
817                 std::max(statePositions.framesAtStandby, statePositions.framesAtFlushOrDrain);
818         *frames = aidlFrames <= mostRecentResetPoint ? 0 : aidlFrames - mostRecentResetPoint;
819     }
820     timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
821     timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
822     return OK;
823 }
824 
presentationComplete()825 status_t StreamOutHalAidl::presentationComplete() {
826     ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
827     return OK;
828 }
829 
updateSourceMetadata(const StreamOutHalInterface::SourceMetadata & sourceMetadata)830 status_t StreamOutHalAidl::updateSourceMetadata(
831         const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
832     TIME_CHECK();
833     if (!mStream) return NO_INIT;
834     ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
835               VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
836     return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
837 }
838 
getDualMonoMode(audio_dual_mono_mode_t * mode)839 status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
840     TIME_CHECK();
841     if (!mStream) return NO_INIT;
842     if (mode == nullptr) {
843         return BAD_VALUE;
844     }
845     ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode;
846     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getDualMonoMode(&aidlMode)));
847     *mode = VALUE_OR_RETURN_STATUS(
848             ::aidl::android::aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(aidlMode));
849     return OK;
850 }
851 
setDualMonoMode(audio_dual_mono_mode_t mode)852 status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
853     TIME_CHECK();
854     if (!mStream) return NO_INIT;
855     ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode = VALUE_OR_RETURN_STATUS(
856             ::aidl::android::legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
857     return statusTFromBinderStatus(mStream->setDualMonoMode(aidlMode));
858 }
859 
getAudioDescriptionMixLevel(float * leveldB)860 status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
861     TIME_CHECK();
862     if (!mStream) return NO_INIT;
863     if (leveldB == nullptr) {
864         return BAD_VALUE;
865     }
866     return statusTFromBinderStatus(mStream->getAudioDescriptionMixLevel(leveldB));
867 }
868 
setAudioDescriptionMixLevel(float leveldB)869 status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB) {
870     TIME_CHECK();
871     if (!mStream) return NO_INIT;
872     return statusTFromBinderStatus(mStream->setAudioDescriptionMixLevel(leveldB));
873 }
874 
getPlaybackRateParameters(audio_playback_rate_t * playbackRate)875 status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
876     TIME_CHECK();
877     if (!mStream) return NO_INIT;
878     if (playbackRate == nullptr) {
879         return BAD_VALUE;
880     }
881     ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate;
882     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getPlaybackRateParameters(&aidlRate)));
883     *playbackRate = VALUE_OR_RETURN_STATUS(
884             ::aidl::android::aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(aidlRate));
885     return OK;
886 }
887 
setPlaybackRateParameters(const audio_playback_rate_t & playbackRate)888 status_t StreamOutHalAidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
889     TIME_CHECK();
890     if (!mStream) return NO_INIT;
891     ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate = VALUE_OR_RETURN_STATUS(
892             ::aidl::android::legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate));
893     return statusTFromBinderStatus(mStream->setPlaybackRateParameters(aidlRate));
894 }
895 
setEventCallback(const sp<StreamOutHalInterfaceEventCallback> & callback)896 status_t StreamOutHalAidl::setEventCallback(
897         const sp<StreamOutHalInterfaceEventCallback>& callback) {
898     TIME_CHECK();
899     if (!mStream) return NO_INIT;
900     if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
901         broker->setStreamOutEventCallback(static_cast<StreamOutHalInterface*>(this), callback);
902     }
903     return OK;
904 }
905 
setLatencyMode(audio_latency_mode_t mode)906 status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode) {
907     TIME_CHECK();
908     if (!mStream) return NO_INIT;
909     ::aidl::android::media::audio::common::AudioLatencyMode aidlMode = VALUE_OR_RETURN_STATUS(
910             ::aidl::android::legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
911     return statusTFromBinderStatus(mStream->setLatencyMode(aidlMode));
912 };
913 
getRecommendedLatencyModes(std::vector<audio_latency_mode_t> * modes)914 status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
915     TIME_CHECK();
916     if (!mStream) return NO_INIT;
917     if (modes == nullptr) {
918         return BAD_VALUE;
919     }
920     std::vector<::aidl::android::media::audio::common::AudioLatencyMode> aidlModes;
921     RETURN_STATUS_IF_ERROR(
922             statusTFromBinderStatus(mStream->getRecommendedLatencyModes(&aidlModes)));
923     *modes = VALUE_OR_RETURN_STATUS(
924             ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
925                     aidlModes,
926                     ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
927     return OK;
928 };
929 
setLatencyModeCallback(const sp<StreamOutHalInterfaceLatencyModeCallback> & callback)930 status_t StreamOutHalAidl::setLatencyModeCallback(
931         const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
932     TIME_CHECK();
933     if (!mStream) return NO_INIT;
934     if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
935         broker->setStreamOutLatencyModeCallback(
936                 static_cast<StreamOutHalInterface*>(this), callback);
937     }
938     return OK;
939 };
940 
exit()941 status_t StreamOutHalAidl::exit() {
942     return StreamHalAidl::exit();
943 }
944 
onWriteReady()945 void StreamOutHalAidl::onWriteReady() {
946     onAsyncTransferReady();
947     if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
948         clientCb->onWriteReady();
949     }
950 }
951 
onDrainReady()952 void StreamOutHalAidl::onDrainReady() {
953     onAsyncDrainReady();
954     if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
955         clientCb->onDrainReady();
956     }
957 }
958 
onError(bool isHardError)959 void StreamOutHalAidl::onError(bool isHardError) {
960     onAsyncError();
961     if (auto clientCb = mClientCallback.load().promote(); clientCb != nullptr) {
962         clientCb->onError(isHardError);
963     }
964 }
965 
filterAndUpdateOffloadMetadata(AudioParameter & parameters)966 status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
967     TIME_CHECK();
968     bool updateMetadata = false;
969     if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
970                 parameters, String8(AudioParameter::keyOffloadCodecAverageBitRate),
971                 [&](int value) {
972                     return value >= 0 ?
973                             mOffloadMetadata.averageBitRatePerSecond = value, OK : BAD_VALUE;
974                 }))) {
975         updateMetadata = true;
976     }
977     if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
978                 parameters, String8(AudioParameter::keyOffloadCodecSampleRate),
979                 [&](int value) {
980                     return value > 0 ? mOffloadMetadata.sampleRate = value, OK : BAD_VALUE;
981                 }))) {
982         updateMetadata = true;
983     }
984     if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
985                 parameters, String8(AudioParameter::keyOffloadCodecChannels),
986                 [&](int value) -> status_t {
987                     if (value > 0) {
988                         audio_channel_mask_t channel_mask = audio_channel_out_mask_from_count(
989                                 static_cast<uint32_t>(value));
990                         if (channel_mask == AUDIO_CHANNEL_INVALID) return BAD_VALUE;
991                         mOffloadMetadata.channelMask = VALUE_OR_RETURN_STATUS(
992                                 ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
993                                         channel_mask, false /*isInput*/));
994                         return OK;
995                     }
996                     return BAD_VALUE;
997                 }))) {
998         updateMetadata = true;
999     }
1000     if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1001                 parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
1002                 [&](int value) {
1003                     // The legacy keys are misnamed, the value is in frames.
1004                     return value >= 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
1005                 }))) {
1006         updateMetadata = true;
1007     }
1008     if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
1009                 parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
1010                 [&](int value) {
1011                     // The legacy keys are misnamed, the value is in frames.
1012                     return value >= 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
1013                 }))) {
1014         updateMetadata = true;
1015     }
1016     if (updateMetadata) {
1017         ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
1018         if (status_t status = statusTFromBinderStatus(
1019                         mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
1020             ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
1021             return status;
1022         }
1023     }
1024     return OK;
1025 }
1026 
1027 // static
1028 ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata & legacy)1029 StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
1030     ::aidl::android::hardware::audio::common::SinkMetadata aidl;
1031     aidl.tracks = VALUE_OR_RETURN(
1032             ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
1033                     legacy.tracks,
1034                     ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
1035     return aidl;
1036 }
1037 
StreamInHalAidl(const audio_config & config,StreamContextAidl && context,int32_t nominalLatency,const std::shared_ptr<IStreamIn> & stream,const std::shared_ptr<IHalAdapterVendorExtension> & vext,const sp<MicrophoneInfoProvider> & micInfoProvider)1038 StreamInHalAidl::StreamInHalAidl(
1039         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
1040         const std::shared_ptr<IStreamIn>& stream,
1041         const std::shared_ptr<IHalAdapterVendorExtension>& vext,
1042         const sp<MicrophoneInfoProvider>& micInfoProvider)
1043         : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
1044                 std::move(context), getStreamCommon(stream), vext),
1045           mStream(stream), mMicInfoProvider(micInfoProvider) {}
1046 
setGain(float gain)1047 status_t StreamInHalAidl::setGain(float gain) {
1048     TIME_CHECK();
1049     if (!mStream) return NO_INIT;
1050     const size_t channelCount = audio_channel_count_from_in_mask(mConfig.channel_mask);
1051     std::vector<float> gains(channelCount != 0 ? channelCount : 1, gain);
1052     return statusTFromBinderStatus(mStream->setHwGain(gains));
1053 }
1054 
read(void * buffer,size_t bytes,size_t * read)1055 status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
1056     if (buffer == nullptr || read == nullptr) {
1057         return BAD_VALUE;
1058     }
1059     return transfer(buffer, bytes, read);
1060 }
1061 
getInputFramesLost(uint32_t * framesLost)1062 status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
1063     if (framesLost == nullptr) {
1064         return BAD_VALUE;
1065     }
1066     int32_t aidlXruns = 0;
1067     RETURN_STATUS_IF_ERROR(getXruns(&aidlXruns));
1068     *framesLost = std::max<int32_t>(0, aidlXruns);
1069     return OK;
1070 }
1071 
getCapturePosition(int64_t * frames,int64_t * time)1072 status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
1073     if (frames == nullptr || time == nullptr) {
1074         return BAD_VALUE;
1075     }
1076     return getObservablePosition(frames, time);
1077 }
1078 
getActiveMicrophones(std::vector<media::MicrophoneInfoFw> * microphones)1079 status_t StreamInHalAidl::getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) {
1080     if (!microphones) {
1081         return BAD_VALUE;
1082     }
1083     TIME_CHECK();
1084     if (!mStream) return NO_INIT;
1085     sp<MicrophoneInfoProvider> micInfoProvider = mMicInfoProvider.promote();
1086     if (!micInfoProvider) return NO_INIT;
1087     auto staticInfo = micInfoProvider->getMicrophoneInfo();
1088     if (!staticInfo) return INVALID_OPERATION;
1089     std::vector<MicrophoneDynamicInfo> dynamicInfo;
1090     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getActiveMicrophones(&dynamicInfo)));
1091     std::vector<media::MicrophoneInfoFw> result;
1092     result.reserve(dynamicInfo.size());
1093     for (const auto& d : dynamicInfo) {
1094         const auto staticInfoIt = std::find_if(staticInfo->begin(), staticInfo->end(),
1095                 [&](const auto& s) { return s.id == d.id; });
1096         if (staticInfoIt != staticInfo->end()) {
1097             // Convert into the c++ backend type from the ndk backend type via the legacy structure.
1098             audio_microphone_characteristic_t legacy = VALUE_OR_RETURN_STATUS(
1099                     ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
1100                             *staticInfoIt, d));
1101             media::MicrophoneInfoFw info = VALUE_OR_RETURN_STATUS(
1102                     ::android::legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
1103                             legacy));
1104             // Note: info.portId is not filled because it's a bit of framework info.
1105             result.push_back(std::move(info));
1106         } else {
1107             ALOGE("%s: no static info for active microphone with id '%s'", __func__, d.id.c_str());
1108         }
1109     }
1110     *microphones = std::move(result);
1111     return OK;
1112 }
1113 
updateSinkMetadata(const StreamInHalInterface::SinkMetadata & sinkMetadata)1114 status_t StreamInHalAidl::updateSinkMetadata(
1115         const StreamInHalInterface::SinkMetadata& sinkMetadata) {
1116     TIME_CHECK();
1117     if (!mStream) return NO_INIT;
1118     ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
1119               VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
1120     return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
1121 }
1122 
setPreferredMicrophoneDirection(audio_microphone_direction_t direction)1123 status_t StreamInHalAidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
1124     TIME_CHECK();
1125     if (!mStream) return NO_INIT;
1126     ::aidl::android::hardware::audio::core::IStreamIn::MicrophoneDirection aidlDirection =
1127               VALUE_OR_RETURN_STATUS(
1128                       ::aidl::android::legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(
1129                               direction));
1130     return statusTFromBinderStatus(mStream->setMicrophoneDirection(aidlDirection));
1131 }
1132 
setPreferredMicrophoneFieldDimension(float zoom)1133 status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom) {
1134     TIME_CHECK();
1135     if (!mStream) return NO_INIT;
1136     return statusTFromBinderStatus(mStream->setMicrophoneFieldDimension(zoom));
1137 }
1138 
1139 } // namespace android
1140