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