1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2016 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 "StreamHalHidl"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <cinttypes>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <android/hidl/manager/1.0/IServiceManager.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <hwbinder/IPCThreadState.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioParameter.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/memory.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/SchedulingPolicyService.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/TimeCheck.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
29*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION >= 4
30*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversion.h>
31*ec779b8eSAndroid Build Coastguard Worker #endif
32*ec779b8eSAndroid Build Coastguard Worker
33*ec779b8eSAndroid Build Coastguard Worker #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
34*ec779b8eSAndroid Build Coastguard Worker #include <HidlUtils.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <util/CoreUtils.h>
36*ec779b8eSAndroid Build Coastguard Worker
37*ec779b8eSAndroid Build Coastguard Worker #include "DeviceHalHidl.h"
38*ec779b8eSAndroid Build Coastguard Worker #include "EffectHalHidl.h"
39*ec779b8eSAndroid Build Coastguard Worker #include "ParameterUtils.h"
40*ec779b8eSAndroid Build Coastguard Worker #include "StreamHalHidl.h"
41*ec779b8eSAndroid Build Coastguard Worker
42*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
43*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
44*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::MQDescriptorSync;
45*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::Return;
46*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::Void;
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker namespace android {
49*ec779b8eSAndroid Build Coastguard Worker
50*ec779b8eSAndroid Build Coastguard Worker using ReadCommand = ::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn::ReadCommand;
51*ec779b8eSAndroid Build Coastguard Worker
52*ec779b8eSAndroid Build Coastguard Worker using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
53*ec779b8eSAndroid Build Coastguard Worker using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
54*ec779b8eSAndroid Build Coastguard Worker
StreamHalHidl(std::string_view className,IStream * stream)55*ec779b8eSAndroid Build Coastguard Worker StreamHalHidl::StreamHalHidl(std::string_view className, IStream *stream)
56*ec779b8eSAndroid Build Coastguard Worker : CoreConversionHelperHidl(className),
57*ec779b8eSAndroid Build Coastguard Worker mStream(stream),
58*ec779b8eSAndroid Build Coastguard Worker mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT),
59*ec779b8eSAndroid Build Coastguard Worker mCachedBufferSize(0){
60*ec779b8eSAndroid Build Coastguard Worker
61*ec779b8eSAndroid Build Coastguard Worker // Instrument audio signal power logging.
62*ec779b8eSAndroid Build Coastguard Worker // Note: This assumes channel mask, format, and sample rate do not change after creation.
63*ec779b8eSAndroid Build Coastguard Worker audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
64*ec779b8eSAndroid Build Coastguard Worker if (/* mStreamPowerLog.isUserDebugOrEngBuild() && */
65*ec779b8eSAndroid Build Coastguard Worker StreamHalHidl::getAudioProperties(&config) == NO_ERROR) {
66*ec779b8eSAndroid Build Coastguard Worker mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
67*ec779b8eSAndroid Build Coastguard Worker }
68*ec779b8eSAndroid Build Coastguard Worker }
69*ec779b8eSAndroid Build Coastguard Worker
~StreamHalHidl()70*ec779b8eSAndroid Build Coastguard Worker StreamHalHidl::~StreamHalHidl() {
71*ec779b8eSAndroid Build Coastguard Worker // The last step is to flush all binder commands so that the deletion
72*ec779b8eSAndroid Build Coastguard Worker // of IStreamIn / IStreamOut (mStream) is issued with less delay. See b/35394629.
73*ec779b8eSAndroid Build Coastguard Worker hardware::IPCThreadState::self()->flushCommands();
74*ec779b8eSAndroid Build Coastguard Worker }
75*ec779b8eSAndroid Build Coastguard Worker
getBufferSize(size_t * size)76*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getBufferSize(size_t *size) {
77*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
78*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
79*ec779b8eSAndroid Build Coastguard Worker status_t status = processReturn("getBufferSize", mStream->getBufferSize(), size);
80*ec779b8eSAndroid Build Coastguard Worker if (status == OK) {
81*ec779b8eSAndroid Build Coastguard Worker mCachedBufferSize = *size;
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker return status;
84*ec779b8eSAndroid Build Coastguard Worker }
85*ec779b8eSAndroid Build Coastguard Worker
getAudioProperties(audio_config_base_t * configBase)86*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getAudioProperties(audio_config_base_t *configBase) {
87*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
88*ec779b8eSAndroid Build Coastguard Worker *configBase = AUDIO_CONFIG_BASE_INITIALIZER;
89*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
90*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION <= 6
91*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getAudioProperties(
92*ec779b8eSAndroid Build Coastguard Worker [&](uint32_t sr, auto m, auto f) {
93*ec779b8eSAndroid Build Coastguard Worker configBase->sample_rate = sr;
94*ec779b8eSAndroid Build Coastguard Worker configBase->channel_mask = static_cast<audio_channel_mask_t>(m);
95*ec779b8eSAndroid Build Coastguard Worker configBase->format = static_cast<audio_format_t>(f);
96*ec779b8eSAndroid Build Coastguard Worker });
97*ec779b8eSAndroid Build Coastguard Worker return processReturn("getAudioProperties", ret);
98*ec779b8eSAndroid Build Coastguard Worker #else
99*ec779b8eSAndroid Build Coastguard Worker Result retval;
100*ec779b8eSAndroid Build Coastguard Worker status_t conversionStatus = BAD_VALUE;
101*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getAudioProperties(
102*ec779b8eSAndroid Build Coastguard Worker [&](Result r, const AudioConfigBase& config) {
103*ec779b8eSAndroid Build Coastguard Worker retval = r;
104*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
105*ec779b8eSAndroid Build Coastguard Worker conversionStatus = HidlUtils::audioConfigBaseToHal(config, configBase);
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker });
108*ec779b8eSAndroid Build Coastguard Worker if (status_t status = processReturn("getAudioProperties", ret, retval); status == NO_ERROR) {
109*ec779b8eSAndroid Build Coastguard Worker return conversionStatus;
110*ec779b8eSAndroid Build Coastguard Worker } else {
111*ec779b8eSAndroid Build Coastguard Worker return status;
112*ec779b8eSAndroid Build Coastguard Worker }
113*ec779b8eSAndroid Build Coastguard Worker #endif
114*ec779b8eSAndroid Build Coastguard Worker }
115*ec779b8eSAndroid Build Coastguard Worker
setParameters(const String8 & kvPairs)116*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::setParameters(const String8& kvPairs) {
117*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
118*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
119*ec779b8eSAndroid Build Coastguard Worker hidl_vec<ParameterValue> hidlParams;
120*ec779b8eSAndroid Build Coastguard Worker status_t status = parametersFromHal(kvPairs, &hidlParams);
121*ec779b8eSAndroid Build Coastguard Worker if (status != OK) return status;
122*ec779b8eSAndroid Build Coastguard Worker return processReturn("setParameters",
123*ec779b8eSAndroid Build Coastguard Worker utils::setParameters(mStream, {} /* context */, hidlParams));
124*ec779b8eSAndroid Build Coastguard Worker }
125*ec779b8eSAndroid Build Coastguard Worker
getParameters(const String8 & keys,String8 * values)126*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getParameters(const String8& keys, String8 *values) {
127*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
128*ec779b8eSAndroid Build Coastguard Worker values->clear();
129*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
130*ec779b8eSAndroid Build Coastguard Worker hidl_vec<hidl_string> hidlKeys;
131*ec779b8eSAndroid Build Coastguard Worker status_t status = keysFromHal(keys, &hidlKeys);
132*ec779b8eSAndroid Build Coastguard Worker if (status != OK) return status;
133*ec779b8eSAndroid Build Coastguard Worker Result retval;
134*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = utils::getParameters(
135*ec779b8eSAndroid Build Coastguard Worker mStream,
136*ec779b8eSAndroid Build Coastguard Worker {} /* context */,
137*ec779b8eSAndroid Build Coastguard Worker hidlKeys,
138*ec779b8eSAndroid Build Coastguard Worker [&](Result r, const hidl_vec<ParameterValue>& parameters) {
139*ec779b8eSAndroid Build Coastguard Worker retval = r;
140*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
141*ec779b8eSAndroid Build Coastguard Worker parametersToHal(parameters, values);
142*ec779b8eSAndroid Build Coastguard Worker }
143*ec779b8eSAndroid Build Coastguard Worker });
144*ec779b8eSAndroid Build Coastguard Worker return processReturn("getParameters", ret, retval);
145*ec779b8eSAndroid Build Coastguard Worker }
146*ec779b8eSAndroid Build Coastguard Worker
addEffect(sp<EffectHalInterface> effect)147*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::addEffect(sp<EffectHalInterface> effect) {
148*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
149*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
150*ec779b8eSAndroid Build Coastguard Worker auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
151*ec779b8eSAndroid Build Coastguard Worker return processReturn("addEffect", mStream->addEffect(hidlEffect->effectId()));
152*ec779b8eSAndroid Build Coastguard Worker }
153*ec779b8eSAndroid Build Coastguard Worker
removeEffect(sp<EffectHalInterface> effect)154*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::removeEffect(sp<EffectHalInterface> effect) {
155*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
156*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
157*ec779b8eSAndroid Build Coastguard Worker auto hidlEffect = sp<effect::EffectHalHidl>::cast(effect);
158*ec779b8eSAndroid Build Coastguard Worker return processReturn("removeEffect", mStream->removeEffect(hidlEffect->effectId()));
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker
standby()161*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::standby() {
162*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
163*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
164*ec779b8eSAndroid Build Coastguard Worker return processReturn("standby", mStream->standby());
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const Vector<String16> & args)167*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::dump(int fd, const Vector<String16>& args) {
168*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
169*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
170*ec779b8eSAndroid Build Coastguard Worker native_handle_t* hidlHandle = native_handle_create(1, 0);
171*ec779b8eSAndroid Build Coastguard Worker hidlHandle->data[0] = fd;
172*ec779b8eSAndroid Build Coastguard Worker hidl_vec<hidl_string> hidlArgs;
173*ec779b8eSAndroid Build Coastguard Worker argsFromHal(args, &hidlArgs);
174*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->debug(hidlHandle, hidlArgs);
175*ec779b8eSAndroid Build Coastguard Worker native_handle_delete(hidlHandle);
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker // TODO(b/111997867, b/177271958) Workaround - remove when fixed.
178*ec779b8eSAndroid Build Coastguard Worker // A Binder transmitted fd may not close immediately due to a race condition b/111997867
179*ec779b8eSAndroid Build Coastguard Worker // when the remote binder thread removes the last refcount to the fd blocks in the
180*ec779b8eSAndroid Build Coastguard Worker // kernel for binder activity. We send a Binder ping() command to unblock the thread
181*ec779b8eSAndroid Build Coastguard Worker // and complete the fd close / release.
182*ec779b8eSAndroid Build Coastguard Worker //
183*ec779b8eSAndroid Build Coastguard Worker // See DeviceHalHidl::dump(), EffectHalHidl::dump(), StreamHalHidl::dump(),
184*ec779b8eSAndroid Build Coastguard Worker // EffectsFactoryHalHidl::dumpEffects().
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker (void)mStream->ping(); // synchronous Binder call
187*ec779b8eSAndroid Build Coastguard Worker
188*ec779b8eSAndroid Build Coastguard Worker mStreamPowerLog.dump(fd);
189*ec779b8eSAndroid Build Coastguard Worker return processReturn("dump", ret);
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker
start()192*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::start() {
193*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
194*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
195*ec779b8eSAndroid Build Coastguard Worker return processReturn("start", mStream->start());
196*ec779b8eSAndroid Build Coastguard Worker }
197*ec779b8eSAndroid Build Coastguard Worker
stop()198*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::stop() {
199*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
200*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
201*ec779b8eSAndroid Build Coastguard Worker return processReturn("stop", mStream->stop());
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker
createMmapBuffer(int32_t minSizeFrames,struct audio_mmap_buffer_info * info)204*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
205*ec779b8eSAndroid Build Coastguard Worker struct audio_mmap_buffer_info *info) {
206*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
207*ec779b8eSAndroid Build Coastguard Worker Result retval;
208*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->createMmapBuffer(
209*ec779b8eSAndroid Build Coastguard Worker minSizeFrames,
210*ec779b8eSAndroid Build Coastguard Worker [&](Result r, const MmapBufferInfo& hidlInfo) {
211*ec779b8eSAndroid Build Coastguard Worker retval = r;
212*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
213*ec779b8eSAndroid Build Coastguard Worker const native_handle *handle = hidlInfo.sharedMemory.handle();
214*ec779b8eSAndroid Build Coastguard Worker if (handle->numFds > 0) {
215*ec779b8eSAndroid Build Coastguard Worker info->shared_memory_fd = handle->data[0];
216*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION >= 4
217*ec779b8eSAndroid Build Coastguard Worker info->flags = audio_mmap_buffer_flag(hidlInfo.flags);
218*ec779b8eSAndroid Build Coastguard Worker #endif
219*ec779b8eSAndroid Build Coastguard Worker info->buffer_size_frames = hidlInfo.bufferSizeFrames;
220*ec779b8eSAndroid Build Coastguard Worker // Negative buffer size frame was a hack in O and P to
221*ec779b8eSAndroid Build Coastguard Worker // indicate that the buffer is shareable to applications
222*ec779b8eSAndroid Build Coastguard Worker if (info->buffer_size_frames < 0) {
223*ec779b8eSAndroid Build Coastguard Worker info->buffer_size_frames *= -1;
224*ec779b8eSAndroid Build Coastguard Worker info->flags = audio_mmap_buffer_flag(
225*ec779b8eSAndroid Build Coastguard Worker info->flags | AUDIO_MMAP_APPLICATION_SHAREABLE);
226*ec779b8eSAndroid Build Coastguard Worker }
227*ec779b8eSAndroid Build Coastguard Worker info->burst_size_frames = hidlInfo.burstSizeFrames;
228*ec779b8eSAndroid Build Coastguard Worker // info->shared_memory_address is not needed in HIDL context
229*ec779b8eSAndroid Build Coastguard Worker info->shared_memory_address = NULL;
230*ec779b8eSAndroid Build Coastguard Worker } else {
231*ec779b8eSAndroid Build Coastguard Worker retval = Result::NOT_INITIALIZED;
232*ec779b8eSAndroid Build Coastguard Worker }
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker });
235*ec779b8eSAndroid Build Coastguard Worker return processReturn("createMmapBuffer", ret, retval);
236*ec779b8eSAndroid Build Coastguard Worker }
237*ec779b8eSAndroid Build Coastguard Worker
getMmapPosition(struct audio_mmap_position * position)238*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
239*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
240*ec779b8eSAndroid Build Coastguard Worker Result retval;
241*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getMmapPosition(
242*ec779b8eSAndroid Build Coastguard Worker [&](Result r, const MmapPosition& hidlPosition) {
243*ec779b8eSAndroid Build Coastguard Worker retval = r;
244*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
245*ec779b8eSAndroid Build Coastguard Worker position->time_nanoseconds = hidlPosition.timeNanoseconds;
246*ec779b8eSAndroid Build Coastguard Worker position->position_frames = hidlPosition.positionFrames;
247*ec779b8eSAndroid Build Coastguard Worker }
248*ec779b8eSAndroid Build Coastguard Worker });
249*ec779b8eSAndroid Build Coastguard Worker return processReturn("getMmapPosition", ret, retval);
250*ec779b8eSAndroid Build Coastguard Worker }
251*ec779b8eSAndroid Build Coastguard Worker
setHalThreadPriority(int priority)252*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::setHalThreadPriority(int priority) {
253*ec779b8eSAndroid Build Coastguard Worker mHalThreadPriority = priority;
254*ec779b8eSAndroid Build Coastguard Worker return OK;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker
getCachedBufferSize(size_t * size)257*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
258*ec779b8eSAndroid Build Coastguard Worker if (mCachedBufferSize != 0) {
259*ec779b8eSAndroid Build Coastguard Worker *size = mCachedBufferSize;
260*ec779b8eSAndroid Build Coastguard Worker return OK;
261*ec779b8eSAndroid Build Coastguard Worker }
262*ec779b8eSAndroid Build Coastguard Worker return getBufferSize(size);
263*ec779b8eSAndroid Build Coastguard Worker }
264*ec779b8eSAndroid Build Coastguard Worker
getHalPid(pid_t * pid)265*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::getHalPid(pid_t *pid) {
266*ec779b8eSAndroid Build Coastguard Worker using ::android::hidl::base::V1_0::DebugInfo;
267*ec779b8eSAndroid Build Coastguard Worker using ::android::hidl::manager::V1_0::IServiceManager;
268*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
269*ec779b8eSAndroid Build Coastguard Worker DebugInfo debugInfo;
270*ec779b8eSAndroid Build Coastguard Worker auto ret = mStream->getDebugInfo([&] (const auto &info) {
271*ec779b8eSAndroid Build Coastguard Worker debugInfo = info;
272*ec779b8eSAndroid Build Coastguard Worker });
273*ec779b8eSAndroid Build Coastguard Worker if (!ret.isOk()) {
274*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
275*ec779b8eSAndroid Build Coastguard Worker }
276*ec779b8eSAndroid Build Coastguard Worker if (debugInfo.pid != (int)IServiceManager::PidConstant::NO_PID) {
277*ec779b8eSAndroid Build Coastguard Worker *pid = debugInfo.pid;
278*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker return NAME_NOT_FOUND;
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker
requestHalThreadPriority(pid_t threadPid,pid_t threadId)283*ec779b8eSAndroid Build Coastguard Worker bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
284*ec779b8eSAndroid Build Coastguard Worker if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
285*ec779b8eSAndroid Build Coastguard Worker return true;
286*ec779b8eSAndroid Build Coastguard Worker }
287*ec779b8eSAndroid Build Coastguard Worker int err = requestPriority(
288*ec779b8eSAndroid Build Coastguard Worker threadPid, threadId,
289*ec779b8eSAndroid Build Coastguard Worker mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
290*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
291*ec779b8eSAndroid Build Coastguard Worker mHalThreadPriority, threadPid, threadId, err);
292*ec779b8eSAndroid Build Coastguard Worker // Audio will still work, but latency will be higher and sometimes unacceptable.
293*ec779b8eSAndroid Build Coastguard Worker return err == 0;
294*ec779b8eSAndroid Build Coastguard Worker }
295*ec779b8eSAndroid Build Coastguard Worker
legacyCreateAudioPatch(const struct audio_port_config & port,std::optional<audio_source_t> source,audio_devices_t type)296*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::legacyCreateAudioPatch(const struct audio_port_config& port,
297*ec779b8eSAndroid Build Coastguard Worker std::optional<audio_source_t> source,
298*ec779b8eSAndroid Build Coastguard Worker audio_devices_t type) {
299*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
300*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(port.type != AUDIO_PORT_TYPE_DEVICE, "port type must be device");
301*ec779b8eSAndroid Build Coastguard Worker unique_malloced_ptr<char> address;
302*ec779b8eSAndroid Build Coastguard Worker if (strcmp(port.ext.device.address, "") != 0) {
303*ec779b8eSAndroid Build Coastguard Worker // FIXME: we only support address on first sink with HAL version < 3.0
304*ec779b8eSAndroid Build Coastguard Worker address.reset(
305*ec779b8eSAndroid Build Coastguard Worker audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address));
306*ec779b8eSAndroid Build Coastguard Worker } else {
307*ec779b8eSAndroid Build Coastguard Worker address.reset((char*)calloc(1, 1));
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker AudioParameter param = AudioParameter(String8(address.get()));
310*ec779b8eSAndroid Build Coastguard Worker param.addInt(String8(AudioParameter::keyRouting), (int)type);
311*ec779b8eSAndroid Build Coastguard Worker if (source.has_value()) {
312*ec779b8eSAndroid Build Coastguard Worker param.addInt(String8(AudioParameter::keyInputSource), (int)source.value());
313*ec779b8eSAndroid Build Coastguard Worker }
314*ec779b8eSAndroid Build Coastguard Worker return setParameters(param.toString());
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker
legacyReleaseAudioPatch()317*ec779b8eSAndroid Build Coastguard Worker status_t StreamHalHidl::legacyReleaseAudioPatch() {
318*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
319*ec779b8eSAndroid Build Coastguard Worker AudioParameter param;
320*ec779b8eSAndroid Build Coastguard Worker param.addInt(String8(AudioParameter::keyRouting), 0);
321*ec779b8eSAndroid Build Coastguard Worker return setParameters(param.toString());
322*ec779b8eSAndroid Build Coastguard Worker }
323*ec779b8eSAndroid Build Coastguard Worker
324*ec779b8eSAndroid Build Coastguard Worker namespace {
325*ec779b8eSAndroid Build Coastguard Worker
326*ec779b8eSAndroid Build Coastguard Worker /* Notes on callback ownership.
327*ec779b8eSAndroid Build Coastguard Worker
328*ec779b8eSAndroid Build Coastguard Worker This is how (Hw)Binder ownership model looks like. The server implementation
329*ec779b8eSAndroid Build Coastguard Worker is owned by Binder framework (via sp<>). Proxies are owned by clients.
330*ec779b8eSAndroid Build Coastguard Worker When the last proxy disappears, Binder framework releases the server impl.
331*ec779b8eSAndroid Build Coastguard Worker
332*ec779b8eSAndroid Build Coastguard Worker Thus, it is not needed to keep any references to StreamOutCallback (this is
333*ec779b8eSAndroid Build Coastguard Worker the server impl) -- it will live as long as HAL server holds a strong ref to
334*ec779b8eSAndroid Build Coastguard Worker IStreamOutCallback proxy. We clear that reference by calling 'clearCallback'
335*ec779b8eSAndroid Build Coastguard Worker from the destructor of StreamOutHalHidl.
336*ec779b8eSAndroid Build Coastguard Worker
337*ec779b8eSAndroid Build Coastguard Worker The callback only keeps a weak reference to the stream. The stream is owned
338*ec779b8eSAndroid Build Coastguard Worker by AudioFlinger.
339*ec779b8eSAndroid Build Coastguard Worker
340*ec779b8eSAndroid Build Coastguard Worker */
341*ec779b8eSAndroid Build Coastguard Worker
342*ec779b8eSAndroid Build Coastguard Worker struct StreamOutCallback : public IStreamOutCallback {
StreamOutCallbackandroid::__anonfdf1219b0711::StreamOutCallback343*ec779b8eSAndroid Build Coastguard Worker StreamOutCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
344*ec779b8eSAndroid Build Coastguard Worker
345*ec779b8eSAndroid Build Coastguard Worker // IStreamOutCallback implementation
onWriteReadyandroid::__anonfdf1219b0711::StreamOutCallback346*ec779b8eSAndroid Build Coastguard Worker Return<void> onWriteReady() override {
347*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalHidl> stream = mStream.promote();
348*ec779b8eSAndroid Build Coastguard Worker if (stream != 0) {
349*ec779b8eSAndroid Build Coastguard Worker stream->onWriteReady();
350*ec779b8eSAndroid Build Coastguard Worker }
351*ec779b8eSAndroid Build Coastguard Worker return Void();
352*ec779b8eSAndroid Build Coastguard Worker }
353*ec779b8eSAndroid Build Coastguard Worker
onDrainReadyandroid::__anonfdf1219b0711::StreamOutCallback354*ec779b8eSAndroid Build Coastguard Worker Return<void> onDrainReady() override {
355*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalHidl> stream = mStream.promote();
356*ec779b8eSAndroid Build Coastguard Worker if (stream != 0) {
357*ec779b8eSAndroid Build Coastguard Worker stream->onDrainReady();
358*ec779b8eSAndroid Build Coastguard Worker }
359*ec779b8eSAndroid Build Coastguard Worker return Void();
360*ec779b8eSAndroid Build Coastguard Worker }
361*ec779b8eSAndroid Build Coastguard Worker
onErrorandroid::__anonfdf1219b0711::StreamOutCallback362*ec779b8eSAndroid Build Coastguard Worker Return<void> onError() override {
363*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalHidl> stream = mStream.promote();
364*ec779b8eSAndroid Build Coastguard Worker if (stream != 0) {
365*ec779b8eSAndroid Build Coastguard Worker stream->onError();
366*ec779b8eSAndroid Build Coastguard Worker }
367*ec779b8eSAndroid Build Coastguard Worker return Void();
368*ec779b8eSAndroid Build Coastguard Worker }
369*ec779b8eSAndroid Build Coastguard Worker
370*ec779b8eSAndroid Build Coastguard Worker private:
371*ec779b8eSAndroid Build Coastguard Worker const wp<StreamOutHalHidl> mStream;
372*ec779b8eSAndroid Build Coastguard Worker };
373*ec779b8eSAndroid Build Coastguard Worker
374*ec779b8eSAndroid Build Coastguard Worker } // namespace
375*ec779b8eSAndroid Build Coastguard Worker
StreamOutHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IStreamOut> & stream)376*ec779b8eSAndroid Build Coastguard Worker StreamOutHalHidl::StreamOutHalHidl(
377*ec779b8eSAndroid Build Coastguard Worker const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& stream)
378*ec779b8eSAndroid Build Coastguard Worker : StreamHalHidl("StreamOutHalHidl", stream.get())
379*ec779b8eSAndroid Build Coastguard Worker , mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
380*ec779b8eSAndroid Build Coastguard Worker }
381*ec779b8eSAndroid Build Coastguard Worker
~StreamOutHalHidl()382*ec779b8eSAndroid Build Coastguard Worker StreamOutHalHidl::~StreamOutHalHidl() {
383*ec779b8eSAndroid Build Coastguard Worker if (mStream != 0) {
384*ec779b8eSAndroid Build Coastguard Worker if (mCallback.load().unsafe_get()) {
385*ec779b8eSAndroid Build Coastguard Worker processReturn("clearCallback", mStream->clearCallback());
386*ec779b8eSAndroid Build Coastguard Worker }
387*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION >= 6
388*ec779b8eSAndroid Build Coastguard Worker if (mEventCallback.load().unsafe_get() != nullptr) {
389*ec779b8eSAndroid Build Coastguard Worker processReturn("setEventCallback",
390*ec779b8eSAndroid Build Coastguard Worker mStream->setEventCallback(nullptr));
391*ec779b8eSAndroid Build Coastguard Worker }
392*ec779b8eSAndroid Build Coastguard Worker #endif
393*ec779b8eSAndroid Build Coastguard Worker processReturn("close", mStream->close());
394*ec779b8eSAndroid Build Coastguard Worker }
395*ec779b8eSAndroid Build Coastguard Worker mCallback = nullptr;
396*ec779b8eSAndroid Build Coastguard Worker mEventCallback = nullptr;
397*ec779b8eSAndroid Build Coastguard Worker if (mEfGroup) {
398*ec779b8eSAndroid Build Coastguard Worker EventFlag::deleteEventFlag(&mEfGroup);
399*ec779b8eSAndroid Build Coastguard Worker }
400*ec779b8eSAndroid Build Coastguard Worker }
401*ec779b8eSAndroid Build Coastguard Worker
getFrameSize(size_t * size)402*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getFrameSize(size_t *size) {
403*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
404*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
405*ec779b8eSAndroid Build Coastguard Worker return processReturn("getFrameSize", mStream->getFrameSize(), size);
406*ec779b8eSAndroid Build Coastguard Worker }
407*ec779b8eSAndroid Build Coastguard Worker
getLatency(uint32_t * latency)408*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
409*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
410*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
411*ec779b8eSAndroid Build Coastguard Worker if (mWriterClient == gettid() && mCommandMQ) {
412*ec779b8eSAndroid Build Coastguard Worker return callWriterThread(
413*ec779b8eSAndroid Build Coastguard Worker WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
414*ec779b8eSAndroid Build Coastguard Worker [&](const WriteStatus& writeStatus) {
415*ec779b8eSAndroid Build Coastguard Worker *latency = writeStatus.reply.latencyMs;
416*ec779b8eSAndroid Build Coastguard Worker });
417*ec779b8eSAndroid Build Coastguard Worker } else {
418*ec779b8eSAndroid Build Coastguard Worker return processReturn("getLatency", mStream->getLatency(), latency);
419*ec779b8eSAndroid Build Coastguard Worker }
420*ec779b8eSAndroid Build Coastguard Worker }
421*ec779b8eSAndroid Build Coastguard Worker
setVolume(float left,float right)422*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setVolume(float left, float right) {
423*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
424*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
425*ec779b8eSAndroid Build Coastguard Worker return processReturn("setVolume", mStream->setVolume(left, right));
426*ec779b8eSAndroid Build Coastguard Worker }
427*ec779b8eSAndroid Build Coastguard Worker
428*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 2
selectPresentation(int presentationId,int programId)429*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
430*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
431*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
432*ec779b8eSAndroid Build Coastguard Worker std::vector<ParameterValue> parameters;
433*ec779b8eSAndroid Build Coastguard Worker String8 halParameters;
434*ec779b8eSAndroid Build Coastguard Worker parameters.push_back({AudioParameter::keyPresentationId, std::to_string(presentationId)});
435*ec779b8eSAndroid Build Coastguard Worker parameters.push_back({AudioParameter::keyProgramId, std::to_string(programId)});
436*ec779b8eSAndroid Build Coastguard Worker parametersToHal(hidl_vec<ParameterValue>(parameters), &halParameters);
437*ec779b8eSAndroid Build Coastguard Worker return setParameters(halParameters);
438*ec779b8eSAndroid Build Coastguard Worker }
439*ec779b8eSAndroid Build Coastguard Worker #elif MAJOR_VERSION >= 4
selectPresentation(int presentationId,int programId)440*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::selectPresentation(int presentationId, int programId) {
441*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
442*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
443*ec779b8eSAndroid Build Coastguard Worker return processReturn("selectPresentation",
444*ec779b8eSAndroid Build Coastguard Worker mStream->selectPresentation(presentationId, programId));
445*ec779b8eSAndroid Build Coastguard Worker }
446*ec779b8eSAndroid Build Coastguard Worker #endif
447*ec779b8eSAndroid Build Coastguard Worker
write(const void * buffer,size_t bytes,size_t * written)448*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
449*ec779b8eSAndroid Build Coastguard Worker // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
450*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
451*ec779b8eSAndroid Build Coastguard Worker *written = 0;
452*ec779b8eSAndroid Build Coastguard Worker
453*ec779b8eSAndroid Build Coastguard Worker if (bytes == 0 && !mDataMQ) {
454*ec779b8eSAndroid Build Coastguard Worker // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
455*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(mCallback.load().unsafe_get(), "First call to async write with 0 bytes");
456*ec779b8eSAndroid Build Coastguard Worker return OK;
457*ec779b8eSAndroid Build Coastguard Worker }
458*ec779b8eSAndroid Build Coastguard Worker
459*ec779b8eSAndroid Build Coastguard Worker status_t status;
460*ec779b8eSAndroid Build Coastguard Worker if (!mDataMQ) {
461*ec779b8eSAndroid Build Coastguard Worker // In case if playback starts close to the end of a compressed track, the bytes
462*ec779b8eSAndroid Build Coastguard Worker // that need to be written is less than the actual buffer size. Need to use
463*ec779b8eSAndroid Build Coastguard Worker // full buffer size for the MQ since otherwise after seeking back to the middle
464*ec779b8eSAndroid Build Coastguard Worker // data will be truncated.
465*ec779b8eSAndroid Build Coastguard Worker size_t bufferSize;
466*ec779b8eSAndroid Build Coastguard Worker if ((status = getCachedBufferSize(&bufferSize)) != OK) {
467*ec779b8eSAndroid Build Coastguard Worker return status;
468*ec779b8eSAndroid Build Coastguard Worker }
469*ec779b8eSAndroid Build Coastguard Worker if (bytes > bufferSize) bufferSize = bytes;
470*ec779b8eSAndroid Build Coastguard Worker if ((status = prepareForWriting(bufferSize)) != OK) {
471*ec779b8eSAndroid Build Coastguard Worker return status;
472*ec779b8eSAndroid Build Coastguard Worker }
473*ec779b8eSAndroid Build Coastguard Worker }
474*ec779b8eSAndroid Build Coastguard Worker
475*ec779b8eSAndroid Build Coastguard Worker status = callWriterThread(
476*ec779b8eSAndroid Build Coastguard Worker WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
477*ec779b8eSAndroid Build Coastguard Worker [&] (const WriteStatus& writeStatus) {
478*ec779b8eSAndroid Build Coastguard Worker *written = writeStatus.reply.written;
479*ec779b8eSAndroid Build Coastguard Worker // Diagnostics of the cause of b/35813113.
480*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(*written > bytes,
481*ec779b8eSAndroid Build Coastguard Worker "hal reports more bytes written than asked for: %lld > %lld",
482*ec779b8eSAndroid Build Coastguard Worker (long long)*written, (long long)bytes);
483*ec779b8eSAndroid Build Coastguard Worker });
484*ec779b8eSAndroid Build Coastguard Worker mStreamPowerLog.log(buffer, *written);
485*ec779b8eSAndroid Build Coastguard Worker return status;
486*ec779b8eSAndroid Build Coastguard Worker }
487*ec779b8eSAndroid Build Coastguard Worker
callWriterThread(WriteCommand cmd,const char * cmdName,const uint8_t * data,size_t dataSize,StreamOutHalHidl::WriterCallback callback)488*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::callWriterThread(
489*ec779b8eSAndroid Build Coastguard Worker WriteCommand cmd, const char* cmdName,
490*ec779b8eSAndroid Build Coastguard Worker const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
491*ec779b8eSAndroid Build Coastguard Worker if (!mCommandMQ->write(&cmd)) {
492*ec779b8eSAndroid Build Coastguard Worker ALOGE("command message queue write failed for \"%s\"", cmdName);
493*ec779b8eSAndroid Build Coastguard Worker return -EAGAIN;
494*ec779b8eSAndroid Build Coastguard Worker }
495*ec779b8eSAndroid Build Coastguard Worker if (data != nullptr) {
496*ec779b8eSAndroid Build Coastguard Worker size_t availableToWrite = mDataMQ->availableToWrite();
497*ec779b8eSAndroid Build Coastguard Worker if (dataSize > availableToWrite) {
498*ec779b8eSAndroid Build Coastguard Worker ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
499*ec779b8eSAndroid Build Coastguard Worker (long long)dataSize, (long long)availableToWrite);
500*ec779b8eSAndroid Build Coastguard Worker dataSize = availableToWrite;
501*ec779b8eSAndroid Build Coastguard Worker }
502*ec779b8eSAndroid Build Coastguard Worker if (!mDataMQ->write(data, dataSize)) {
503*ec779b8eSAndroid Build Coastguard Worker ALOGE("data message queue write failed for \"%s\"", cmdName);
504*ec779b8eSAndroid Build Coastguard Worker }
505*ec779b8eSAndroid Build Coastguard Worker }
506*ec779b8eSAndroid Build Coastguard Worker mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
507*ec779b8eSAndroid Build Coastguard Worker
508*ec779b8eSAndroid Build Coastguard Worker // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
509*ec779b8eSAndroid Build Coastguard Worker uint32_t efState = 0;
510*ec779b8eSAndroid Build Coastguard Worker retry:
511*ec779b8eSAndroid Build Coastguard Worker status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
512*ec779b8eSAndroid Build Coastguard Worker if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
513*ec779b8eSAndroid Build Coastguard Worker WriteStatus writeStatus;
514*ec779b8eSAndroid Build Coastguard Worker writeStatus.retval = Result::NOT_INITIALIZED;
515*ec779b8eSAndroid Build Coastguard Worker if (!mStatusMQ->read(&writeStatus)) {
516*ec779b8eSAndroid Build Coastguard Worker ALOGE("status message read failed for \"%s\"", cmdName);
517*ec779b8eSAndroid Build Coastguard Worker }
518*ec779b8eSAndroid Build Coastguard Worker if (writeStatus.retval == Result::OK) {
519*ec779b8eSAndroid Build Coastguard Worker ret = OK;
520*ec779b8eSAndroid Build Coastguard Worker callback(writeStatus);
521*ec779b8eSAndroid Build Coastguard Worker } else {
522*ec779b8eSAndroid Build Coastguard Worker ret = processReturn(cmdName, writeStatus.retval);
523*ec779b8eSAndroid Build Coastguard Worker }
524*ec779b8eSAndroid Build Coastguard Worker return ret;
525*ec779b8eSAndroid Build Coastguard Worker }
526*ec779b8eSAndroid Build Coastguard Worker if (ret == -EAGAIN || ret == -EINTR) {
527*ec779b8eSAndroid Build Coastguard Worker // Spurious wakeup. This normally retries no more than once.
528*ec779b8eSAndroid Build Coastguard Worker goto retry;
529*ec779b8eSAndroid Build Coastguard Worker }
530*ec779b8eSAndroid Build Coastguard Worker return ret;
531*ec779b8eSAndroid Build Coastguard Worker }
532*ec779b8eSAndroid Build Coastguard Worker
prepareForWriting(size_t bufferSize)533*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
534*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<CommandMQ> tempCommandMQ;
535*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<DataMQ> tempDataMQ;
536*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<StatusMQ> tempStatusMQ;
537*ec779b8eSAndroid Build Coastguard Worker Result retval;
538*ec779b8eSAndroid Build Coastguard Worker pid_t halThreadPid, halThreadTid;
539*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->prepareForWriting(
540*ec779b8eSAndroid Build Coastguard Worker 1, bufferSize,
541*ec779b8eSAndroid Build Coastguard Worker [&](Result r,
542*ec779b8eSAndroid Build Coastguard Worker const CommandMQ::Descriptor& commandMQ,
543*ec779b8eSAndroid Build Coastguard Worker const DataMQ::Descriptor& dataMQ,
544*ec779b8eSAndroid Build Coastguard Worker const StatusMQ::Descriptor& statusMQ,
545*ec779b8eSAndroid Build Coastguard Worker const auto& halThreadInfo) {
546*ec779b8eSAndroid Build Coastguard Worker retval = r;
547*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
548*ec779b8eSAndroid Build Coastguard Worker tempCommandMQ.reset(new CommandMQ(commandMQ));
549*ec779b8eSAndroid Build Coastguard Worker tempDataMQ.reset(new DataMQ(dataMQ));
550*ec779b8eSAndroid Build Coastguard Worker tempStatusMQ.reset(new StatusMQ(statusMQ));
551*ec779b8eSAndroid Build Coastguard Worker if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
552*ec779b8eSAndroid Build Coastguard Worker EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
553*ec779b8eSAndroid Build Coastguard Worker }
554*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION <= 6
555*ec779b8eSAndroid Build Coastguard Worker halThreadPid = halThreadInfo.pid;
556*ec779b8eSAndroid Build Coastguard Worker halThreadTid = halThreadInfo.tid;
557*ec779b8eSAndroid Build Coastguard Worker #else
558*ec779b8eSAndroid Build Coastguard Worker halThreadTid = halThreadInfo;
559*ec779b8eSAndroid Build Coastguard Worker #endif
560*ec779b8eSAndroid Build Coastguard Worker }
561*ec779b8eSAndroid Build Coastguard Worker });
562*ec779b8eSAndroid Build Coastguard Worker if (!ret.isOk() || retval != Result::OK) {
563*ec779b8eSAndroid Build Coastguard Worker return processReturn("prepareForWriting", ret, retval);
564*ec779b8eSAndroid Build Coastguard Worker }
565*ec779b8eSAndroid Build Coastguard Worker if (!tempCommandMQ || !tempCommandMQ->isValid() ||
566*ec779b8eSAndroid Build Coastguard Worker !tempDataMQ || !tempDataMQ->isValid() ||
567*ec779b8eSAndroid Build Coastguard Worker !tempStatusMQ || !tempStatusMQ->isValid() ||
568*ec779b8eSAndroid Build Coastguard Worker !mEfGroup) {
569*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
570*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
571*ec779b8eSAndroid Build Coastguard Worker "Command message queue for writing is invalid");
572*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
573*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
574*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
575*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
576*ec779b8eSAndroid Build Coastguard Worker "Status message queue for writing is invalid");
577*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
578*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
579*ec779b8eSAndroid Build Coastguard Worker }
580*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION >= 7
581*ec779b8eSAndroid Build Coastguard Worker if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
582*ec779b8eSAndroid Build Coastguard Worker return status;
583*ec779b8eSAndroid Build Coastguard Worker }
584*ec779b8eSAndroid Build Coastguard Worker #endif
585*ec779b8eSAndroid Build Coastguard Worker requestHalThreadPriority(halThreadPid, halThreadTid);
586*ec779b8eSAndroid Build Coastguard Worker
587*ec779b8eSAndroid Build Coastguard Worker mCommandMQ = std::move(tempCommandMQ);
588*ec779b8eSAndroid Build Coastguard Worker mDataMQ = std::move(tempDataMQ);
589*ec779b8eSAndroid Build Coastguard Worker mStatusMQ = std::move(tempStatusMQ);
590*ec779b8eSAndroid Build Coastguard Worker mWriterClient = gettid();
591*ec779b8eSAndroid Build Coastguard Worker return OK;
592*ec779b8eSAndroid Build Coastguard Worker }
593*ec779b8eSAndroid Build Coastguard Worker
getRenderPosition(uint64_t * dspFrames)594*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getRenderPosition(uint64_t *dspFrames) {
595*ec779b8eSAndroid Build Coastguard Worker // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
596*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
597*ec779b8eSAndroid Build Coastguard Worker Result retval;
598*ec779b8eSAndroid Build Coastguard Worker uint32_t halPosition = 0;
599*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getRenderPosition(
600*ec779b8eSAndroid Build Coastguard Worker [&](Result r, uint32_t d) {
601*ec779b8eSAndroid Build Coastguard Worker retval = r;
602*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
603*ec779b8eSAndroid Build Coastguard Worker halPosition = d;
604*ec779b8eSAndroid Build Coastguard Worker }
605*ec779b8eSAndroid Build Coastguard Worker });
606*ec779b8eSAndroid Build Coastguard Worker status_t status = processReturn("getRenderPosition", ret, retval);
607*ec779b8eSAndroid Build Coastguard Worker if (status != OK) {
608*ec779b8eSAndroid Build Coastguard Worker return status;
609*ec779b8eSAndroid Build Coastguard Worker }
610*ec779b8eSAndroid Build Coastguard Worker // Maintain a 64-bit render position using the 32-bit result from the HAL.
611*ec779b8eSAndroid Build Coastguard Worker // This delta calculation relies on the arithmetic overflow behavior
612*ec779b8eSAndroid Build Coastguard Worker // of integers. For example (100 - 0xFFFFFFF0) = 116.
613*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mPositionMutex);
614*ec779b8eSAndroid Build Coastguard Worker const auto truncatedPosition = (uint32_t)mRenderPosition;
615*ec779b8eSAndroid Build Coastguard Worker int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow()
616*ec779b8eSAndroid Build Coastguard Worker (void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition);
617*ec779b8eSAndroid Build Coastguard Worker
618*ec779b8eSAndroid Build Coastguard Worker if (deltaHalPosition >= 0) {
619*ec779b8eSAndroid Build Coastguard Worker mRenderPosition += deltaHalPosition;
620*ec779b8eSAndroid Build Coastguard Worker } else if (mExpectRetrograde) {
621*ec779b8eSAndroid Build Coastguard Worker mExpectRetrograde = false;
622*ec779b8eSAndroid Build Coastguard Worker mRenderPosition -= static_cast<uint64_t>(-deltaHalPosition);
623*ec779b8eSAndroid Build Coastguard Worker ALOGW("Retrograde motion of %" PRId32 " frames", -deltaHalPosition);
624*ec779b8eSAndroid Build Coastguard Worker }
625*ec779b8eSAndroid Build Coastguard Worker *dspFrames = mRenderPosition;
626*ec779b8eSAndroid Build Coastguard Worker return OK;
627*ec779b8eSAndroid Build Coastguard Worker }
628*ec779b8eSAndroid Build Coastguard Worker
setCallback(wp<StreamOutHalInterfaceCallback> callback)629*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
630*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
631*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
632*ec779b8eSAndroid Build Coastguard Worker status_t status = processReturn(
633*ec779b8eSAndroid Build Coastguard Worker "setCallback", mStream->setCallback(new StreamOutCallback(this)));
634*ec779b8eSAndroid Build Coastguard Worker if (status == OK) {
635*ec779b8eSAndroid Build Coastguard Worker mCallback = callback;
636*ec779b8eSAndroid Build Coastguard Worker }
637*ec779b8eSAndroid Build Coastguard Worker return status;
638*ec779b8eSAndroid Build Coastguard Worker }
639*ec779b8eSAndroid Build Coastguard Worker
supportsPauseAndResume(bool * supportsPause,bool * supportsResume)640*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
641*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
642*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
643*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->supportsPauseAndResume(
644*ec779b8eSAndroid Build Coastguard Worker [&](bool p, bool r) {
645*ec779b8eSAndroid Build Coastguard Worker *supportsPause = p;
646*ec779b8eSAndroid Build Coastguard Worker *supportsResume = r;
647*ec779b8eSAndroid Build Coastguard Worker });
648*ec779b8eSAndroid Build Coastguard Worker return processReturn("supportsPauseAndResume", ret);
649*ec779b8eSAndroid Build Coastguard Worker }
650*ec779b8eSAndroid Build Coastguard Worker
pause()651*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::pause() {
652*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
653*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
654*ec779b8eSAndroid Build Coastguard Worker return processReturn("pause", mStream->pause());
655*ec779b8eSAndroid Build Coastguard Worker }
656*ec779b8eSAndroid Build Coastguard Worker
resume()657*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::resume() {
658*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
659*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
660*ec779b8eSAndroid Build Coastguard Worker return processReturn("pause", mStream->resume());
661*ec779b8eSAndroid Build Coastguard Worker }
662*ec779b8eSAndroid Build Coastguard Worker
supportsDrain(bool * supportsDrain)663*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::supportsDrain(bool *supportsDrain) {
664*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
665*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
666*ec779b8eSAndroid Build Coastguard Worker return processReturn("supportsDrain", mStream->supportsDrain(), supportsDrain);
667*ec779b8eSAndroid Build Coastguard Worker }
668*ec779b8eSAndroid Build Coastguard Worker
drain(bool earlyNotify)669*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::drain(bool earlyNotify) {
670*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
671*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
672*ec779b8eSAndroid Build Coastguard Worker return processReturn(
673*ec779b8eSAndroid Build Coastguard Worker "drain", mStream->drain(earlyNotify ? AudioDrain::EARLY_NOTIFY : AudioDrain::ALL));
674*ec779b8eSAndroid Build Coastguard Worker }
675*ec779b8eSAndroid Build Coastguard Worker
flush()676*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::flush() {
677*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
678*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
679*ec779b8eSAndroid Build Coastguard Worker {
680*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mPositionMutex);
681*ec779b8eSAndroid Build Coastguard Worker mRenderPosition = 0;
682*ec779b8eSAndroid Build Coastguard Worker mExpectRetrograde = false;
683*ec779b8eSAndroid Build Coastguard Worker }
684*ec779b8eSAndroid Build Coastguard Worker return processReturn("pause", mStream->flush());
685*ec779b8eSAndroid Build Coastguard Worker }
686*ec779b8eSAndroid Build Coastguard Worker
standby()687*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::standby() {
688*ec779b8eSAndroid Build Coastguard Worker {
689*ec779b8eSAndroid Build Coastguard Worker std::lock_guard l(mPositionMutex);
690*ec779b8eSAndroid Build Coastguard Worker mRenderPosition = 0;
691*ec779b8eSAndroid Build Coastguard Worker mExpectRetrograde = false;
692*ec779b8eSAndroid Build Coastguard Worker }
693*ec779b8eSAndroid Build Coastguard Worker return StreamHalHidl::standby();
694*ec779b8eSAndroid Build Coastguard Worker }
695*ec779b8eSAndroid Build Coastguard Worker
getPresentationPosition(uint64_t * frames,struct timespec * timestamp)696*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
697*ec779b8eSAndroid Build Coastguard Worker // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
698*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
699*ec779b8eSAndroid Build Coastguard Worker if (mWriterClient == gettid() && mCommandMQ) {
700*ec779b8eSAndroid Build Coastguard Worker return callWriterThread(
701*ec779b8eSAndroid Build Coastguard Worker WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
702*ec779b8eSAndroid Build Coastguard Worker [&](const WriteStatus& writeStatus) {
703*ec779b8eSAndroid Build Coastguard Worker *frames = writeStatus.reply.presentationPosition.frames;
704*ec779b8eSAndroid Build Coastguard Worker timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
705*ec779b8eSAndroid Build Coastguard Worker timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
706*ec779b8eSAndroid Build Coastguard Worker });
707*ec779b8eSAndroid Build Coastguard Worker } else {
708*ec779b8eSAndroid Build Coastguard Worker Result retval;
709*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getPresentationPosition(
710*ec779b8eSAndroid Build Coastguard Worker [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
711*ec779b8eSAndroid Build Coastguard Worker retval = r;
712*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
713*ec779b8eSAndroid Build Coastguard Worker *frames = hidlFrames;
714*ec779b8eSAndroid Build Coastguard Worker timestamp->tv_sec = hidlTimeStamp.tvSec;
715*ec779b8eSAndroid Build Coastguard Worker timestamp->tv_nsec = hidlTimeStamp.tvNSec;
716*ec779b8eSAndroid Build Coastguard Worker }
717*ec779b8eSAndroid Build Coastguard Worker });
718*ec779b8eSAndroid Build Coastguard Worker return processReturn("getPresentationPosition", ret, retval);
719*ec779b8eSAndroid Build Coastguard Worker }
720*ec779b8eSAndroid Build Coastguard Worker }
721*ec779b8eSAndroid Build Coastguard Worker
presentationComplete()722*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::presentationComplete() {
723*ec779b8eSAndroid Build Coastguard Worker // Avoid suppressing retrograde motion in mRenderPosition for gapless offload/direct when
724*ec779b8eSAndroid Build Coastguard Worker // transitioning between tracks.
725*ec779b8eSAndroid Build Coastguard Worker // The HAL resets the frame position without flush/stop being called, but calls back prior to
726*ec779b8eSAndroid Build Coastguard Worker // this event. So, on the next occurrence of retrograde motion, we permit backwards movement of
727*ec779b8eSAndroid Build Coastguard Worker // mRenderPosition.
728*ec779b8eSAndroid Build Coastguard Worker mExpectRetrograde = true;
729*ec779b8eSAndroid Build Coastguard Worker return OK;
730*ec779b8eSAndroid Build Coastguard Worker }
731*ec779b8eSAndroid Build Coastguard Worker
732*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 2
updateSourceMetadata(const StreamOutHalInterface::SourceMetadata &)733*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::updateSourceMetadata(
734*ec779b8eSAndroid Build Coastguard Worker const StreamOutHalInterface::SourceMetadata& /* sourceMetadata */) {
735*ec779b8eSAndroid Build Coastguard Worker // Audio HAL V2.0 does not support propagating source metadata
736*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
737*ec779b8eSAndroid Build Coastguard Worker }
738*ec779b8eSAndroid Build Coastguard Worker #elif MAJOR_VERSION >= 4
updateSourceMetadata(const StreamOutHalInterface::SourceMetadata & sourceMetadata)739*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::updateSourceMetadata(
740*ec779b8eSAndroid Build Coastguard Worker const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
741*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
742*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 4
743*ec779b8eSAndroid Build Coastguard Worker ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
744*ec779b8eSAndroid Build Coastguard Worker #else
745*ec779b8eSAndroid Build Coastguard Worker ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
746*ec779b8eSAndroid Build Coastguard Worker #endif
747*ec779b8eSAndroid Build Coastguard Worker if (status_t status = CoreUtils::sourceMetadataFromHalV7(
748*ec779b8eSAndroid Build Coastguard Worker sourceMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
749*ec779b8eSAndroid Build Coastguard Worker status != OK) {
750*ec779b8eSAndroid Build Coastguard Worker return status;
751*ec779b8eSAndroid Build Coastguard Worker }
752*ec779b8eSAndroid Build Coastguard Worker return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(hidlMetadata));
753*ec779b8eSAndroid Build Coastguard Worker }
754*ec779b8eSAndroid Build Coastguard Worker #endif
755*ec779b8eSAndroid Build Coastguard Worker
756*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION < 6
getDualMonoMode(audio_dual_mono_mode_t * mode __unused)757*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
758*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
759*ec779b8eSAndroid Build Coastguard Worker }
760*ec779b8eSAndroid Build Coastguard Worker
setDualMonoMode(audio_dual_mono_mode_t mode __unused)761*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
762*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
763*ec779b8eSAndroid Build Coastguard Worker }
764*ec779b8eSAndroid Build Coastguard Worker
getAudioDescriptionMixLevel(float * leveldB __unused)765*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
766*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
767*ec779b8eSAndroid Build Coastguard Worker }
768*ec779b8eSAndroid Build Coastguard Worker
setAudioDescriptionMixLevel(float leveldB __unused)769*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB __unused) {
770*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
771*ec779b8eSAndroid Build Coastguard Worker }
772*ec779b8eSAndroid Build Coastguard Worker
getPlaybackRateParameters(audio_playback_rate_t * playbackRate __unused)773*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getPlaybackRateParameters(
774*ec779b8eSAndroid Build Coastguard Worker audio_playback_rate_t* playbackRate __unused) {
775*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
776*ec779b8eSAndroid Build Coastguard Worker }
777*ec779b8eSAndroid Build Coastguard Worker
setPlaybackRateParameters(const audio_playback_rate_t & playbackRate __unused)778*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setPlaybackRateParameters(
779*ec779b8eSAndroid Build Coastguard Worker const audio_playback_rate_t& playbackRate __unused) {
780*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
781*ec779b8eSAndroid Build Coastguard Worker }
782*ec779b8eSAndroid Build Coastguard Worker
setEventCallback(const sp<StreamOutHalInterfaceEventCallback> & callback __unused)783*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setEventCallback(
784*ec779b8eSAndroid Build Coastguard Worker const sp<StreamOutHalInterfaceEventCallback>& callback __unused) {
785*ec779b8eSAndroid Build Coastguard Worker // Codec format callback is supported starting from audio HAL V6.0
786*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
787*ec779b8eSAndroid Build Coastguard Worker }
788*ec779b8eSAndroid Build Coastguard Worker
789*ec779b8eSAndroid Build Coastguard Worker #else
790*ec779b8eSAndroid Build Coastguard Worker
getDualMonoMode(audio_dual_mono_mode_t * mode)791*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
792*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
793*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
794*ec779b8eSAndroid Build Coastguard Worker Result retval;
795*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getDualMonoMode(
796*ec779b8eSAndroid Build Coastguard Worker [&](Result r, DualMonoMode hidlMode) {
797*ec779b8eSAndroid Build Coastguard Worker retval = r;
798*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
799*ec779b8eSAndroid Build Coastguard Worker *mode = static_cast<audio_dual_mono_mode_t>(hidlMode);
800*ec779b8eSAndroid Build Coastguard Worker }
801*ec779b8eSAndroid Build Coastguard Worker });
802*ec779b8eSAndroid Build Coastguard Worker return processReturn("getDualMonoMode", ret, retval);
803*ec779b8eSAndroid Build Coastguard Worker }
804*ec779b8eSAndroid Build Coastguard Worker
setDualMonoMode(audio_dual_mono_mode_t mode)805*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
806*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
807*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
808*ec779b8eSAndroid Build Coastguard Worker return processReturn(
809*ec779b8eSAndroid Build Coastguard Worker "setDualMonoMode", mStream->setDualMonoMode(static_cast<DualMonoMode>(mode)));
810*ec779b8eSAndroid Build Coastguard Worker }
811*ec779b8eSAndroid Build Coastguard Worker
getAudioDescriptionMixLevel(float * leveldB)812*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getAudioDescriptionMixLevel(float* leveldB) {
813*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
814*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
815*ec779b8eSAndroid Build Coastguard Worker Result retval;
816*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getAudioDescriptionMixLevel(
817*ec779b8eSAndroid Build Coastguard Worker [&](Result r, float hidlLeveldB) {
818*ec779b8eSAndroid Build Coastguard Worker retval = r;
819*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
820*ec779b8eSAndroid Build Coastguard Worker *leveldB = hidlLeveldB;
821*ec779b8eSAndroid Build Coastguard Worker }
822*ec779b8eSAndroid Build Coastguard Worker });
823*ec779b8eSAndroid Build Coastguard Worker return processReturn("getAudioDescriptionMixLevel", ret, retval);
824*ec779b8eSAndroid Build Coastguard Worker }
825*ec779b8eSAndroid Build Coastguard Worker
setAudioDescriptionMixLevel(float leveldB)826*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setAudioDescriptionMixLevel(float leveldB) {
827*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
828*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
829*ec779b8eSAndroid Build Coastguard Worker return processReturn(
830*ec779b8eSAndroid Build Coastguard Worker "setAudioDescriptionMixLevel", mStream->setAudioDescriptionMixLevel(leveldB));
831*ec779b8eSAndroid Build Coastguard Worker }
832*ec779b8eSAndroid Build Coastguard Worker
getPlaybackRateParameters(audio_playback_rate_t * playbackRate)833*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
834*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
835*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
836*ec779b8eSAndroid Build Coastguard Worker Result retval;
837*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getPlaybackRateParameters(
838*ec779b8eSAndroid Build Coastguard Worker [&](Result r, PlaybackRate hidlPlaybackRate) {
839*ec779b8eSAndroid Build Coastguard Worker retval = r;
840*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
841*ec779b8eSAndroid Build Coastguard Worker playbackRate->mSpeed = hidlPlaybackRate.speed;
842*ec779b8eSAndroid Build Coastguard Worker playbackRate->mPitch = hidlPlaybackRate.pitch;
843*ec779b8eSAndroid Build Coastguard Worker playbackRate->mStretchMode =
844*ec779b8eSAndroid Build Coastguard Worker static_cast<audio_timestretch_stretch_mode_t>(
845*ec779b8eSAndroid Build Coastguard Worker hidlPlaybackRate.timestretchMode);
846*ec779b8eSAndroid Build Coastguard Worker playbackRate->mFallbackMode =
847*ec779b8eSAndroid Build Coastguard Worker static_cast<audio_timestretch_fallback_mode_t>(
848*ec779b8eSAndroid Build Coastguard Worker hidlPlaybackRate.fallbackMode);
849*ec779b8eSAndroid Build Coastguard Worker }
850*ec779b8eSAndroid Build Coastguard Worker });
851*ec779b8eSAndroid Build Coastguard Worker return processReturn("getPlaybackRateParameters", ret, retval);
852*ec779b8eSAndroid Build Coastguard Worker }
853*ec779b8eSAndroid Build Coastguard Worker
setPlaybackRateParameters(const audio_playback_rate_t & playbackRate)854*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
855*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
856*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
857*ec779b8eSAndroid Build Coastguard Worker return processReturn(
858*ec779b8eSAndroid Build Coastguard Worker "setPlaybackRateParameters", mStream->setPlaybackRateParameters(
859*ec779b8eSAndroid Build Coastguard Worker PlaybackRate{playbackRate.mSpeed, playbackRate.mPitch,
860*ec779b8eSAndroid Build Coastguard Worker static_cast<TimestretchMode>(playbackRate.mStretchMode),
861*ec779b8eSAndroid Build Coastguard Worker static_cast<TimestretchFallbackMode>(playbackRate.mFallbackMode)}));
862*ec779b8eSAndroid Build Coastguard Worker }
863*ec779b8eSAndroid Build Coastguard Worker
864*ec779b8eSAndroid Build Coastguard Worker #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutEventCallback.h)
865*ec779b8eSAndroid Build Coastguard Worker
866*ec779b8eSAndroid Build Coastguard Worker namespace {
867*ec779b8eSAndroid Build Coastguard Worker
868*ec779b8eSAndroid Build Coastguard Worker struct StreamOutEventCallback : public IStreamOutEventCallback {
StreamOutEventCallbackandroid::__anonfdf1219b1211::StreamOutEventCallback869*ec779b8eSAndroid Build Coastguard Worker StreamOutEventCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
870*ec779b8eSAndroid Build Coastguard Worker
871*ec779b8eSAndroid Build Coastguard Worker // IStreamOutEventCallback implementation
onCodecFormatChangedandroid::__anonfdf1219b1211::StreamOutEventCallback872*ec779b8eSAndroid Build Coastguard Worker Return<void> onCodecFormatChanged(
873*ec779b8eSAndroid Build Coastguard Worker const android::hardware::hidl_vec<uint8_t>& audioMetadata) override {
874*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalHidl> stream = mStream.promote();
875*ec779b8eSAndroid Build Coastguard Worker if (stream != nullptr) {
876*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t> metadataBs(audioMetadata.begin(), audioMetadata.end());
877*ec779b8eSAndroid Build Coastguard Worker stream->onCodecFormatChanged(metadataBs);
878*ec779b8eSAndroid Build Coastguard Worker }
879*ec779b8eSAndroid Build Coastguard Worker return Void();
880*ec779b8eSAndroid Build Coastguard Worker }
881*ec779b8eSAndroid Build Coastguard Worker
882*ec779b8eSAndroid Build Coastguard Worker private:
883*ec779b8eSAndroid Build Coastguard Worker wp<StreamOutHalHidl> mStream;
884*ec779b8eSAndroid Build Coastguard Worker };
885*ec779b8eSAndroid Build Coastguard Worker
886*ec779b8eSAndroid Build Coastguard Worker } // namespace
887*ec779b8eSAndroid Build Coastguard Worker
setEventCallback(const sp<StreamOutHalInterfaceEventCallback> & callback)888*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setEventCallback(
889*ec779b8eSAndroid Build Coastguard Worker const sp<StreamOutHalInterfaceEventCallback>& callback) {
890*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
891*ec779b8eSAndroid Build Coastguard Worker if (mStream == nullptr) return NO_INIT;
892*ec779b8eSAndroid Build Coastguard Worker mEventCallback = callback;
893*ec779b8eSAndroid Build Coastguard Worker status_t status = processReturn(
894*ec779b8eSAndroid Build Coastguard Worker "setEventCallback",
895*ec779b8eSAndroid Build Coastguard Worker mStream->setEventCallback(
896*ec779b8eSAndroid Build Coastguard Worker callback.get() == nullptr ? nullptr : new StreamOutEventCallback(this)));
897*ec779b8eSAndroid Build Coastguard Worker return status;
898*ec779b8eSAndroid Build Coastguard Worker }
899*ec779b8eSAndroid Build Coastguard Worker #endif
900*ec779b8eSAndroid Build Coastguard Worker
901*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
902*ec779b8eSAndroid Build Coastguard Worker using hardware::audio::V7_1::LatencyMode;
903*ec779b8eSAndroid Build Coastguard Worker
setLatencyMode(audio_latency_mode_t mode)904*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode) {
905*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
906*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
907*ec779b8eSAndroid Build Coastguard Worker return processReturn(
908*ec779b8eSAndroid Build Coastguard Worker "setLatencyMode", mStream->setLatencyMode(static_cast<LatencyMode>(mode)));
909*ec779b8eSAndroid Build Coastguard Worker };
910*ec779b8eSAndroid Build Coastguard Worker
getRecommendedLatencyModes(std::vector<audio_latency_mode_t> * modes)911*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
912*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
913*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
914*ec779b8eSAndroid Build Coastguard Worker Result retval;
915*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getRecommendedLatencyModes(
916*ec779b8eSAndroid Build Coastguard Worker [&](Result r, hidl_vec<LatencyMode> hidlModes) {
917*ec779b8eSAndroid Build Coastguard Worker retval = r;
918*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < hidlModes.size(); i++) {
919*ec779b8eSAndroid Build Coastguard Worker modes->push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
920*ec779b8eSAndroid Build Coastguard Worker }
921*ec779b8eSAndroid Build Coastguard Worker });
922*ec779b8eSAndroid Build Coastguard Worker return processReturn("getRecommendedLatencyModes", ret, retval);
923*ec779b8eSAndroid Build Coastguard Worker };
924*ec779b8eSAndroid Build Coastguard Worker
925*ec779b8eSAndroid Build Coastguard Worker #include PATH(android/hardware/audio/FILE_VERSION/IStreamOutLatencyModeCallback.h)
926*ec779b8eSAndroid Build Coastguard Worker
927*ec779b8eSAndroid Build Coastguard Worker using hardware::audio::V7_1::IStreamOutLatencyModeCallback;
928*ec779b8eSAndroid Build Coastguard Worker
929*ec779b8eSAndroid Build Coastguard Worker namespace {
930*ec779b8eSAndroid Build Coastguard Worker struct StreamOutLatencyModeCallback : public IStreamOutLatencyModeCallback {
StreamOutLatencyModeCallbackandroid::__anonfdf1219b1411::StreamOutLatencyModeCallback931*ec779b8eSAndroid Build Coastguard Worker StreamOutLatencyModeCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
932*ec779b8eSAndroid Build Coastguard Worker
933*ec779b8eSAndroid Build Coastguard Worker // IStreamOutLatencyModeCallback implementation
onRecommendedLatencyModeChangedandroid::__anonfdf1219b1411::StreamOutLatencyModeCallback934*ec779b8eSAndroid Build Coastguard Worker Return<void> onRecommendedLatencyModeChanged(const hidl_vec<LatencyMode>& hidlModes) override {
935*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalHidl> stream = mStream.promote();
936*ec779b8eSAndroid Build Coastguard Worker if (stream != nullptr) {
937*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_latency_mode_t> modes;
938*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < hidlModes.size(); i++) {
939*ec779b8eSAndroid Build Coastguard Worker modes.push_back(static_cast<audio_latency_mode_t>(hidlModes[i]));
940*ec779b8eSAndroid Build Coastguard Worker }
941*ec779b8eSAndroid Build Coastguard Worker stream->onRecommendedLatencyModeChanged(modes);
942*ec779b8eSAndroid Build Coastguard Worker }
943*ec779b8eSAndroid Build Coastguard Worker return Void();
944*ec779b8eSAndroid Build Coastguard Worker }
945*ec779b8eSAndroid Build Coastguard Worker
946*ec779b8eSAndroid Build Coastguard Worker private:
947*ec779b8eSAndroid Build Coastguard Worker wp<StreamOutHalHidl> mStream;
948*ec779b8eSAndroid Build Coastguard Worker };
949*ec779b8eSAndroid Build Coastguard Worker } // namespace
950*ec779b8eSAndroid Build Coastguard Worker
setLatencyModeCallback(const sp<StreamOutHalInterfaceLatencyModeCallback> & callback)951*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setLatencyModeCallback(
952*ec779b8eSAndroid Build Coastguard Worker const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
953*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
954*ec779b8eSAndroid Build Coastguard Worker
955*ec779b8eSAndroid Build Coastguard Worker if (mStream == nullptr) return NO_INIT;
956*ec779b8eSAndroid Build Coastguard Worker mLatencyModeCallback = callback;
957*ec779b8eSAndroid Build Coastguard Worker status_t status = processReturn(
958*ec779b8eSAndroid Build Coastguard Worker "setLatencyModeCallback",
959*ec779b8eSAndroid Build Coastguard Worker mStream->setLatencyModeCallback(
960*ec779b8eSAndroid Build Coastguard Worker callback.get() == nullptr ? nullptr : new StreamOutLatencyModeCallback(this)));
961*ec779b8eSAndroid Build Coastguard Worker return status;
962*ec779b8eSAndroid Build Coastguard Worker };
963*ec779b8eSAndroid Build Coastguard Worker
964*ec779b8eSAndroid Build Coastguard Worker #else
965*ec779b8eSAndroid Build Coastguard Worker
setLatencyMode(audio_latency_mode_t mode __unused)966*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setLatencyMode(audio_latency_mode_t mode __unused) {
967*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
968*ec779b8eSAndroid Build Coastguard Worker };
969*ec779b8eSAndroid Build Coastguard Worker
getRecommendedLatencyModes(std::vector<audio_latency_mode_t> * modes __unused)970*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::getRecommendedLatencyModes(
971*ec779b8eSAndroid Build Coastguard Worker std::vector<audio_latency_mode_t> *modes __unused) {
972*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
973*ec779b8eSAndroid Build Coastguard Worker };
974*ec779b8eSAndroid Build Coastguard Worker
setLatencyModeCallback(const sp<StreamOutHalInterfaceLatencyModeCallback> & callback __unused)975*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::setLatencyModeCallback(
976*ec779b8eSAndroid Build Coastguard Worker const sp<StreamOutHalInterfaceLatencyModeCallback>& callback __unused) {
977*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
978*ec779b8eSAndroid Build Coastguard Worker };
979*ec779b8eSAndroid Build Coastguard Worker
980*ec779b8eSAndroid Build Coastguard Worker #endif
981*ec779b8eSAndroid Build Coastguard Worker
onWriteReady()982*ec779b8eSAndroid Build Coastguard Worker void StreamOutHalHidl::onWriteReady() {
983*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
984*ec779b8eSAndroid Build Coastguard Worker if (callback == 0) return;
985*ec779b8eSAndroid Build Coastguard Worker ALOGV("asyncCallback onWriteReady");
986*ec779b8eSAndroid Build Coastguard Worker callback->onWriteReady();
987*ec779b8eSAndroid Build Coastguard Worker }
988*ec779b8eSAndroid Build Coastguard Worker
onDrainReady()989*ec779b8eSAndroid Build Coastguard Worker void StreamOutHalHidl::onDrainReady() {
990*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
991*ec779b8eSAndroid Build Coastguard Worker if (callback == 0) return;
992*ec779b8eSAndroid Build Coastguard Worker ALOGV("asyncCallback onDrainReady");
993*ec779b8eSAndroid Build Coastguard Worker callback->onDrainReady();
994*ec779b8eSAndroid Build Coastguard Worker }
995*ec779b8eSAndroid Build Coastguard Worker
onError()996*ec779b8eSAndroid Build Coastguard Worker void StreamOutHalHidl::onError() {
997*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalInterfaceCallback> callback = mCallback.load().promote();
998*ec779b8eSAndroid Build Coastguard Worker if (callback == 0) return;
999*ec779b8eSAndroid Build Coastguard Worker ALOGV("asyncCallback onError");
1000*ec779b8eSAndroid Build Coastguard Worker callback->onError(false /*isHardError*/);
1001*ec779b8eSAndroid Build Coastguard Worker }
1002*ec779b8eSAndroid Build Coastguard Worker
onCodecFormatChanged(const std::vector<uint8_t> & metadataBs)1003*ec779b8eSAndroid Build Coastguard Worker void StreamOutHalHidl::onCodecFormatChanged(const std::vector<uint8_t>& metadataBs) {
1004*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalInterfaceEventCallback> callback = mEventCallback.load().promote();
1005*ec779b8eSAndroid Build Coastguard Worker if (callback == nullptr) return;
1006*ec779b8eSAndroid Build Coastguard Worker ALOGV("asyncCodecFormatCallback %s", __func__);
1007*ec779b8eSAndroid Build Coastguard Worker callback->onCodecFormatChanged(metadataBs);
1008*ec779b8eSAndroid Build Coastguard Worker }
1009*ec779b8eSAndroid Build Coastguard Worker
onRecommendedLatencyModeChanged(const std::vector<audio_latency_mode_t> & modes)1010*ec779b8eSAndroid Build Coastguard Worker void StreamOutHalHidl::onRecommendedLatencyModeChanged(
1011*ec779b8eSAndroid Build Coastguard Worker const std::vector<audio_latency_mode_t>& modes) {
1012*ec779b8eSAndroid Build Coastguard Worker sp<StreamOutHalInterfaceLatencyModeCallback> callback = mLatencyModeCallback.load().promote();
1013*ec779b8eSAndroid Build Coastguard Worker if (callback == nullptr) return;
1014*ec779b8eSAndroid Build Coastguard Worker callback->onRecommendedLatencyModeChanged(modes);
1015*ec779b8eSAndroid Build Coastguard Worker }
1016*ec779b8eSAndroid Build Coastguard Worker
exit()1017*ec779b8eSAndroid Build Coastguard Worker status_t StreamOutHalHidl::exit() {
1018*ec779b8eSAndroid Build Coastguard Worker // Signal exiting to HALs that use intermediate pipes to close them.
1019*ec779b8eSAndroid Build Coastguard Worker AudioParameter param;
1020*ec779b8eSAndroid Build Coastguard Worker param.addInt(String8(AudioParameter::keyExiting), 1);
1021*ec779b8eSAndroid Build Coastguard Worker param.add(String8(AudioParameter::keyClosing), String8(AudioParameter::valueTrue));
1022*ec779b8eSAndroid Build Coastguard Worker return setParameters(param.toString());
1023*ec779b8eSAndroid Build Coastguard Worker }
1024*ec779b8eSAndroid Build Coastguard Worker
StreamInHalHidl(const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn> & stream)1025*ec779b8eSAndroid Build Coastguard Worker StreamInHalHidl::StreamInHalHidl(
1026*ec779b8eSAndroid Build Coastguard Worker const sp<::android::hardware::audio::CORE_TYPES_CPP_VERSION::IStreamIn>& stream)
1027*ec779b8eSAndroid Build Coastguard Worker : StreamHalHidl("StreamInHalHidl", stream.get())
1028*ec779b8eSAndroid Build Coastguard Worker , mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
1029*ec779b8eSAndroid Build Coastguard Worker }
1030*ec779b8eSAndroid Build Coastguard Worker
~StreamInHalHidl()1031*ec779b8eSAndroid Build Coastguard Worker StreamInHalHidl::~StreamInHalHidl() {
1032*ec779b8eSAndroid Build Coastguard Worker if (mStream != 0) {
1033*ec779b8eSAndroid Build Coastguard Worker processReturn("close", mStream->close());
1034*ec779b8eSAndroid Build Coastguard Worker }
1035*ec779b8eSAndroid Build Coastguard Worker if (mEfGroup) {
1036*ec779b8eSAndroid Build Coastguard Worker EventFlag::deleteEventFlag(&mEfGroup);
1037*ec779b8eSAndroid Build Coastguard Worker }
1038*ec779b8eSAndroid Build Coastguard Worker }
1039*ec779b8eSAndroid Build Coastguard Worker
getFrameSize(size_t * size)1040*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::getFrameSize(size_t *size) {
1041*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1042*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1043*ec779b8eSAndroid Build Coastguard Worker return processReturn("getFrameSize", mStream->getFrameSize(), size);
1044*ec779b8eSAndroid Build Coastguard Worker }
1045*ec779b8eSAndroid Build Coastguard Worker
setGain(float gain)1046*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::setGain(float gain) {
1047*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1048*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1049*ec779b8eSAndroid Build Coastguard Worker return processReturn("setGain", mStream->setGain(gain));
1050*ec779b8eSAndroid Build Coastguard Worker }
1051*ec779b8eSAndroid Build Coastguard Worker
read(void * buffer,size_t bytes,size_t * read)1052*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
1053*ec779b8eSAndroid Build Coastguard Worker // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
1054*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1055*ec779b8eSAndroid Build Coastguard Worker *read = 0;
1056*ec779b8eSAndroid Build Coastguard Worker
1057*ec779b8eSAndroid Build Coastguard Worker if (bytes == 0 && !mDataMQ) {
1058*ec779b8eSAndroid Build Coastguard Worker // Can't determine the size for the MQ buffer. Wait for a non-empty read request.
1059*ec779b8eSAndroid Build Coastguard Worker return OK;
1060*ec779b8eSAndroid Build Coastguard Worker }
1061*ec779b8eSAndroid Build Coastguard Worker
1062*ec779b8eSAndroid Build Coastguard Worker status_t status;
1063*ec779b8eSAndroid Build Coastguard Worker if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
1064*ec779b8eSAndroid Build Coastguard Worker return status;
1065*ec779b8eSAndroid Build Coastguard Worker }
1066*ec779b8eSAndroid Build Coastguard Worker
1067*ec779b8eSAndroid Build Coastguard Worker ReadParameters params;
1068*ec779b8eSAndroid Build Coastguard Worker params.command = ReadCommand::READ;
1069*ec779b8eSAndroid Build Coastguard Worker params.params.read = bytes;
1070*ec779b8eSAndroid Build Coastguard Worker status = callReaderThread(params, "read",
1071*ec779b8eSAndroid Build Coastguard Worker [&](const ReadStatus& readStatus) {
1072*ec779b8eSAndroid Build Coastguard Worker const size_t availToRead = mDataMQ->availableToRead();
1073*ec779b8eSAndroid Build Coastguard Worker if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
1074*ec779b8eSAndroid Build Coastguard Worker ALOGE("data message queue read failed for \"read\"");
1075*ec779b8eSAndroid Build Coastguard Worker }
1076*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(availToRead != readStatus.reply.read,
1077*ec779b8eSAndroid Build Coastguard Worker "HAL read report inconsistent: mq = %d, status = %d",
1078*ec779b8eSAndroid Build Coastguard Worker (int32_t)availToRead, (int32_t)readStatus.reply.read);
1079*ec779b8eSAndroid Build Coastguard Worker *read = readStatus.reply.read;
1080*ec779b8eSAndroid Build Coastguard Worker });
1081*ec779b8eSAndroid Build Coastguard Worker mStreamPowerLog.log(buffer, *read);
1082*ec779b8eSAndroid Build Coastguard Worker return status;
1083*ec779b8eSAndroid Build Coastguard Worker }
1084*ec779b8eSAndroid Build Coastguard Worker
callReaderThread(const ReadParameters & params,const char * cmdName,StreamInHalHidl::ReaderCallback callback)1085*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::callReaderThread(
1086*ec779b8eSAndroid Build Coastguard Worker const ReadParameters& params, const char* cmdName,
1087*ec779b8eSAndroid Build Coastguard Worker StreamInHalHidl::ReaderCallback callback) {
1088*ec779b8eSAndroid Build Coastguard Worker if (!mCommandMQ->write(¶ms)) {
1089*ec779b8eSAndroid Build Coastguard Worker ALOGW("command message queue write failed");
1090*ec779b8eSAndroid Build Coastguard Worker return -EAGAIN;
1091*ec779b8eSAndroid Build Coastguard Worker }
1092*ec779b8eSAndroid Build Coastguard Worker mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
1093*ec779b8eSAndroid Build Coastguard Worker
1094*ec779b8eSAndroid Build Coastguard Worker // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
1095*ec779b8eSAndroid Build Coastguard Worker uint32_t efState = 0;
1096*ec779b8eSAndroid Build Coastguard Worker retry:
1097*ec779b8eSAndroid Build Coastguard Worker status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
1098*ec779b8eSAndroid Build Coastguard Worker if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
1099*ec779b8eSAndroid Build Coastguard Worker ReadStatus readStatus;
1100*ec779b8eSAndroid Build Coastguard Worker readStatus.retval = Result::NOT_INITIALIZED;
1101*ec779b8eSAndroid Build Coastguard Worker if (!mStatusMQ->read(&readStatus)) {
1102*ec779b8eSAndroid Build Coastguard Worker ALOGE("status message read failed for \"%s\"", cmdName);
1103*ec779b8eSAndroid Build Coastguard Worker }
1104*ec779b8eSAndroid Build Coastguard Worker if (readStatus.retval == Result::OK) {
1105*ec779b8eSAndroid Build Coastguard Worker ret = OK;
1106*ec779b8eSAndroid Build Coastguard Worker callback(readStatus);
1107*ec779b8eSAndroid Build Coastguard Worker } else {
1108*ec779b8eSAndroid Build Coastguard Worker ret = processReturn(cmdName, readStatus.retval);
1109*ec779b8eSAndroid Build Coastguard Worker }
1110*ec779b8eSAndroid Build Coastguard Worker return ret;
1111*ec779b8eSAndroid Build Coastguard Worker }
1112*ec779b8eSAndroid Build Coastguard Worker if (ret == -EAGAIN || ret == -EINTR) {
1113*ec779b8eSAndroid Build Coastguard Worker // Spurious wakeup. This normally retries no more than once.
1114*ec779b8eSAndroid Build Coastguard Worker goto retry;
1115*ec779b8eSAndroid Build Coastguard Worker }
1116*ec779b8eSAndroid Build Coastguard Worker return ret;
1117*ec779b8eSAndroid Build Coastguard Worker }
1118*ec779b8eSAndroid Build Coastguard Worker
prepareForReading(size_t bufferSize)1119*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
1120*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<CommandMQ> tempCommandMQ;
1121*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<DataMQ> tempDataMQ;
1122*ec779b8eSAndroid Build Coastguard Worker std::unique_ptr<StatusMQ> tempStatusMQ;
1123*ec779b8eSAndroid Build Coastguard Worker Result retval;
1124*ec779b8eSAndroid Build Coastguard Worker pid_t halThreadPid, halThreadTid;
1125*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->prepareForReading(
1126*ec779b8eSAndroid Build Coastguard Worker 1, bufferSize,
1127*ec779b8eSAndroid Build Coastguard Worker [&](Result r,
1128*ec779b8eSAndroid Build Coastguard Worker const CommandMQ::Descriptor& commandMQ,
1129*ec779b8eSAndroid Build Coastguard Worker const DataMQ::Descriptor& dataMQ,
1130*ec779b8eSAndroid Build Coastguard Worker const StatusMQ::Descriptor& statusMQ,
1131*ec779b8eSAndroid Build Coastguard Worker const auto& halThreadInfo) {
1132*ec779b8eSAndroid Build Coastguard Worker retval = r;
1133*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
1134*ec779b8eSAndroid Build Coastguard Worker tempCommandMQ.reset(new CommandMQ(commandMQ));
1135*ec779b8eSAndroid Build Coastguard Worker tempDataMQ.reset(new DataMQ(dataMQ));
1136*ec779b8eSAndroid Build Coastguard Worker tempStatusMQ.reset(new StatusMQ(statusMQ));
1137*ec779b8eSAndroid Build Coastguard Worker if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
1138*ec779b8eSAndroid Build Coastguard Worker EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
1139*ec779b8eSAndroid Build Coastguard Worker }
1140*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION <= 6
1141*ec779b8eSAndroid Build Coastguard Worker halThreadPid = halThreadInfo.pid;
1142*ec779b8eSAndroid Build Coastguard Worker halThreadTid = halThreadInfo.tid;
1143*ec779b8eSAndroid Build Coastguard Worker #else
1144*ec779b8eSAndroid Build Coastguard Worker halThreadTid = halThreadInfo;
1145*ec779b8eSAndroid Build Coastguard Worker #endif
1146*ec779b8eSAndroid Build Coastguard Worker }
1147*ec779b8eSAndroid Build Coastguard Worker });
1148*ec779b8eSAndroid Build Coastguard Worker if (!ret.isOk() || retval != Result::OK) {
1149*ec779b8eSAndroid Build Coastguard Worker return processReturn("prepareForReading", ret, retval);
1150*ec779b8eSAndroid Build Coastguard Worker }
1151*ec779b8eSAndroid Build Coastguard Worker if (!tempCommandMQ || !tempCommandMQ->isValid() ||
1152*ec779b8eSAndroid Build Coastguard Worker !tempDataMQ || !tempDataMQ->isValid() ||
1153*ec779b8eSAndroid Build Coastguard Worker !tempStatusMQ || !tempStatusMQ->isValid() ||
1154*ec779b8eSAndroid Build Coastguard Worker !mEfGroup) {
1155*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
1156*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
1157*ec779b8eSAndroid Build Coastguard Worker "Command message queue for writing is invalid");
1158*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
1159*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
1160*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
1161*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
1162*ec779b8eSAndroid Build Coastguard Worker "Status message queue for reading is invalid");
1163*ec779b8eSAndroid Build Coastguard Worker ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
1164*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
1165*ec779b8eSAndroid Build Coastguard Worker }
1166*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION >= 7
1167*ec779b8eSAndroid Build Coastguard Worker if (status_t status = getHalPid(&halThreadPid); status != NO_ERROR) {
1168*ec779b8eSAndroid Build Coastguard Worker return status;
1169*ec779b8eSAndroid Build Coastguard Worker }
1170*ec779b8eSAndroid Build Coastguard Worker #endif
1171*ec779b8eSAndroid Build Coastguard Worker requestHalThreadPriority(halThreadPid, halThreadTid);
1172*ec779b8eSAndroid Build Coastguard Worker
1173*ec779b8eSAndroid Build Coastguard Worker mCommandMQ = std::move(tempCommandMQ);
1174*ec779b8eSAndroid Build Coastguard Worker mDataMQ = std::move(tempDataMQ);
1175*ec779b8eSAndroid Build Coastguard Worker mStatusMQ = std::move(tempStatusMQ);
1176*ec779b8eSAndroid Build Coastguard Worker mReaderClient = gettid();
1177*ec779b8eSAndroid Build Coastguard Worker return OK;
1178*ec779b8eSAndroid Build Coastguard Worker }
1179*ec779b8eSAndroid Build Coastguard Worker
getInputFramesLost(uint32_t * framesLost)1180*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::getInputFramesLost(uint32_t *framesLost) {
1181*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1182*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1183*ec779b8eSAndroid Build Coastguard Worker return processReturn("getInputFramesLost", mStream->getInputFramesLost(), framesLost);
1184*ec779b8eSAndroid Build Coastguard Worker }
1185*ec779b8eSAndroid Build Coastguard Worker
getCapturePosition(int64_t * frames,int64_t * time)1186*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
1187*ec779b8eSAndroid Build Coastguard Worker // TIME_CHECK(); // TODO(b/243839867) reenable only when optimized.
1188*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1189*ec779b8eSAndroid Build Coastguard Worker if (mReaderClient == gettid() && mCommandMQ) {
1190*ec779b8eSAndroid Build Coastguard Worker ReadParameters params;
1191*ec779b8eSAndroid Build Coastguard Worker params.command = ReadCommand::GET_CAPTURE_POSITION;
1192*ec779b8eSAndroid Build Coastguard Worker return callReaderThread(params, "getCapturePosition",
1193*ec779b8eSAndroid Build Coastguard Worker [&](const ReadStatus& readStatus) {
1194*ec779b8eSAndroid Build Coastguard Worker *frames = readStatus.reply.capturePosition.frames;
1195*ec779b8eSAndroid Build Coastguard Worker *time = readStatus.reply.capturePosition.time;
1196*ec779b8eSAndroid Build Coastguard Worker });
1197*ec779b8eSAndroid Build Coastguard Worker } else {
1198*ec779b8eSAndroid Build Coastguard Worker Result retval;
1199*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getCapturePosition(
1200*ec779b8eSAndroid Build Coastguard Worker [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
1201*ec779b8eSAndroid Build Coastguard Worker retval = r;
1202*ec779b8eSAndroid Build Coastguard Worker if (retval == Result::OK) {
1203*ec779b8eSAndroid Build Coastguard Worker *frames = hidlFrames;
1204*ec779b8eSAndroid Build Coastguard Worker *time = hidlTime;
1205*ec779b8eSAndroid Build Coastguard Worker }
1206*ec779b8eSAndroid Build Coastguard Worker });
1207*ec779b8eSAndroid Build Coastguard Worker return processReturn("getCapturePosition", ret, retval);
1208*ec779b8eSAndroid Build Coastguard Worker }
1209*ec779b8eSAndroid Build Coastguard Worker }
1210*ec779b8eSAndroid Build Coastguard Worker
1211*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 2
getActiveMicrophones(std::vector<media::MicrophoneInfoFw> * microphones __unused)1212*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::getActiveMicrophones(
1213*ec779b8eSAndroid Build Coastguard Worker std::vector<media::MicrophoneInfoFw> *microphones __unused) {
1214*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1215*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1216*ec779b8eSAndroid Build Coastguard Worker }
1217*ec779b8eSAndroid Build Coastguard Worker
updateSinkMetadata(const StreamInHalInterface::SinkMetadata &)1218*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::updateSinkMetadata(
1219*ec779b8eSAndroid Build Coastguard Worker const StreamInHalInterface::SinkMetadata& /* sinkMetadata */) {
1220*ec779b8eSAndroid Build Coastguard Worker // Audio HAL V2.0 does not support propagating sink metadata
1221*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1222*ec779b8eSAndroid Build Coastguard Worker }
1223*ec779b8eSAndroid Build Coastguard Worker
1224*ec779b8eSAndroid Build Coastguard Worker #elif MAJOR_VERSION >= 4
getActiveMicrophones(std::vector<media::MicrophoneInfoFw> * microphonesInfo)1225*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::getActiveMicrophones(
1226*ec779b8eSAndroid Build Coastguard Worker std::vector<media::MicrophoneInfoFw> *microphonesInfo) {
1227*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1228*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
1229*ec779b8eSAndroid Build Coastguard Worker Result retval;
1230*ec779b8eSAndroid Build Coastguard Worker Return<void> ret = mStream->getActiveMicrophones(
1231*ec779b8eSAndroid Build Coastguard Worker [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
1232*ec779b8eSAndroid Build Coastguard Worker retval = r;
1233*ec779b8eSAndroid Build Coastguard Worker for (size_t k = 0; k < micArrayHal.size(); k++) {
1234*ec779b8eSAndroid Build Coastguard Worker // Convert via legacy.
1235*ec779b8eSAndroid Build Coastguard Worker audio_microphone_characteristic_t dst;
1236*ec779b8eSAndroid Build Coastguard Worker (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
1237*ec779b8eSAndroid Build Coastguard Worker auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(dst);
1238*ec779b8eSAndroid Build Coastguard Worker if (conv.ok()) {
1239*ec779b8eSAndroid Build Coastguard Worker microphonesInfo->push_back(conv.value());
1240*ec779b8eSAndroid Build Coastguard Worker } else {
1241*ec779b8eSAndroid Build Coastguard Worker ALOGW("getActiveMicrophones: could not convert %s to AIDL: %d",
1242*ec779b8eSAndroid Build Coastguard Worker toString(micArrayHal[k]).c_str(), conv.error());
1243*ec779b8eSAndroid Build Coastguard Worker microphonesInfo->push_back(media::MicrophoneInfoFw{});
1244*ec779b8eSAndroid Build Coastguard Worker }
1245*ec779b8eSAndroid Build Coastguard Worker }
1246*ec779b8eSAndroid Build Coastguard Worker });
1247*ec779b8eSAndroid Build Coastguard Worker return processReturn("getActiveMicrophones", ret, retval);
1248*ec779b8eSAndroid Build Coastguard Worker }
1249*ec779b8eSAndroid Build Coastguard Worker
updateSinkMetadata(const StreamInHalInterface::SinkMetadata & sinkMetadata)1250*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::updateSinkMetadata(const
1251*ec779b8eSAndroid Build Coastguard Worker StreamInHalInterface::SinkMetadata& sinkMetadata) {
1252*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1253*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION == 4
1254*ec779b8eSAndroid Build Coastguard Worker ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1255*ec779b8eSAndroid Build Coastguard Worker #else
1256*ec779b8eSAndroid Build Coastguard Worker ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SinkMetadata hidlMetadata;
1257*ec779b8eSAndroid Build Coastguard Worker #endif
1258*ec779b8eSAndroid Build Coastguard Worker if (status_t status = CoreUtils::sinkMetadataFromHalV7(
1259*ec779b8eSAndroid Build Coastguard Worker sinkMetadata.tracks, true /*ignoreNonVendorTags*/, &hidlMetadata);
1260*ec779b8eSAndroid Build Coastguard Worker status != OK) {
1261*ec779b8eSAndroid Build Coastguard Worker return status;
1262*ec779b8eSAndroid Build Coastguard Worker }
1263*ec779b8eSAndroid Build Coastguard Worker return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(hidlMetadata));
1264*ec779b8eSAndroid Build Coastguard Worker }
1265*ec779b8eSAndroid Build Coastguard Worker #endif
1266*ec779b8eSAndroid Build Coastguard Worker
1267*ec779b8eSAndroid Build Coastguard Worker #if MAJOR_VERSION < 5
setPreferredMicrophoneDirection(audio_microphone_direction_t direction __unused)1268*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::setPreferredMicrophoneDirection(
1269*ec779b8eSAndroid Build Coastguard Worker audio_microphone_direction_t direction __unused) {
1270*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1271*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1272*ec779b8eSAndroid Build Coastguard Worker }
1273*ec779b8eSAndroid Build Coastguard Worker
setPreferredMicrophoneFieldDimension(float zoom __unused)1274*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
1275*ec779b8eSAndroid Build Coastguard Worker if (mStream == 0) return NO_INIT;
1276*ec779b8eSAndroid Build Coastguard Worker return INVALID_OPERATION;
1277*ec779b8eSAndroid Build Coastguard Worker }
1278*ec779b8eSAndroid Build Coastguard Worker #else
setPreferredMicrophoneDirection(audio_microphone_direction_t direction)1279*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
1280*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1281*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
1282*ec779b8eSAndroid Build Coastguard Worker return processReturn("setPreferredMicrophoneDirection",
1283*ec779b8eSAndroid Build Coastguard Worker mStream->setMicrophoneDirection(static_cast<MicrophoneDirection>(direction)));
1284*ec779b8eSAndroid Build Coastguard Worker }
1285*ec779b8eSAndroid Build Coastguard Worker
setPreferredMicrophoneFieldDimension(float zoom)1286*ec779b8eSAndroid Build Coastguard Worker status_t StreamInHalHidl::setPreferredMicrophoneFieldDimension(float zoom) {
1287*ec779b8eSAndroid Build Coastguard Worker TIME_CHECK();
1288*ec779b8eSAndroid Build Coastguard Worker if (!mStream) return NO_INIT;
1289*ec779b8eSAndroid Build Coastguard Worker return processReturn("setPreferredMicrophoneFieldDimension",
1290*ec779b8eSAndroid Build Coastguard Worker mStream->setMicrophoneFieldDimension(zoom));
1291*ec779b8eSAndroid Build Coastguard Worker }
1292*ec779b8eSAndroid Build Coastguard Worker #endif
1293*ec779b8eSAndroid Build Coastguard Worker
1294*ec779b8eSAndroid Build Coastguard Worker } // namespace android
1295