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 ¶meters) {
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