1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "StreamInHAL"
18 
19 #include "core/default/StreamIn.h"
20 #include "core/default/Util.h"
21 #include "common/all-versions/HidlSupport.h"
22 
23 //#define LOG_NDEBUG 0
24 #define ATRACE_TAG ATRACE_TAG_AUDIO
25 
26 #include <HidlUtils.h>
27 #include <android/log.h>
28 #include <hardware/audio.h>
29 #include <util/CoreUtils.h>
30 #include <utils/Trace.h>
31 #include <cmath>
32 #include <memory>
33 
34 namespace android {
35 namespace hardware {
36 namespace audio {
37 namespace CPP_VERSION {
38 namespace implementation {
39 
40 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
41 
42 namespace {
43 
44 class ReadThread : public Thread {
45    public:
46     // ReadThread's lifespan never exceeds StreamIn's lifespan.
ReadThread(std::atomic<bool> * stop,audio_stream_in_t * stream,StreamIn::CommandMQ * commandMQ,StreamIn::DataMQ * dataMQ,StreamIn::StatusMQ * statusMQ,EventFlag * efGroup)47     ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ,
48                StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
49         : Thread(false /*canCallJava*/),
50           mStop(stop),
51           mStream(stream),
52           mCommandMQ(commandMQ),
53           mDataMQ(dataMQ),
54           mStatusMQ(statusMQ),
55           mEfGroup(efGroup),
56           mBuffer(nullptr) {}
init()57     bool init() {
58         mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
59         return mBuffer != nullptr;
60     }
~ReadThread()61     virtual ~ReadThread() {}
62 
63    private:
64     std::atomic<bool>* mStop;
65     audio_stream_in_t* mStream;
66     StreamIn::CommandMQ* mCommandMQ;
67     StreamIn::DataMQ* mDataMQ;
68     StreamIn::StatusMQ* mStatusMQ;
69     EventFlag* mEfGroup;
70     std::unique_ptr<uint8_t[]> mBuffer;
71     IStreamIn::ReadParameters mParameters;
72     IStreamIn::ReadStatus mStatus;
73 
74     bool threadLoop() override;
75 
76     void doGetCapturePosition();
77     void doRead();
78 };
79 
doRead()80 void ReadThread::doRead() {
81     size_t availableToWrite = mDataMQ->availableToWrite();
82     size_t requestedToRead = mParameters.params.read;
83     if (requestedToRead > availableToWrite) {
84         ALOGW(
85             "truncating read data from %d to %d due to insufficient data queue "
86             "space",
87             (int32_t)requestedToRead, (int32_t)availableToWrite);
88         requestedToRead = availableToWrite;
89     }
90     ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
91     mStatus.retval = Result::OK;
92     if (readResult >= 0) {
93         mStatus.reply.read = readResult;
94         if (!mDataMQ->write(&mBuffer[0], readResult)) {
95             ALOGW("data message queue write failed");
96         }
97     } else {
98         mStatus.retval = Stream::analyzeStatus("read", readResult);
99     }
100 }
101 
doGetCapturePosition()102 void ReadThread::doGetCapturePosition() {
103     mStatus.retval = StreamIn::getCapturePositionImpl(
104         mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
105 }
106 
threadLoop()107 bool ReadThread::threadLoop() {
108     // This implementation doesn't return control back to the Thread until it
109     // decides to stop,
110     // as the Thread uses mutexes, and this can lead to priority inversion.
111     while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
112         uint32_t efState = 0;
113         mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
114         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
115             continue;  // Nothing to do.
116         }
117         if (!mCommandMQ->read(&mParameters)) {
118             continue;  // Nothing to do.
119         }
120         mStatus.replyTo = mParameters.command;
121         switch (mParameters.command) {
122             case IStreamIn::ReadCommand::READ:
123                 doRead();
124                 break;
125             case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
126                 doGetCapturePosition();
127                 break;
128             default:
129                 ALOGE("Unknown read thread command code %d", mParameters.command);
130                 mStatus.retval = Result::NOT_SUPPORTED;
131                 break;
132         }
133         if (!mStatusMQ->write(&mStatus)) {
134             ALOGW("status message queue write failed");
135         }
136         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
137     }
138 
139     return false;
140 }
141 
142 }  // namespace
143 
StreamIn(const sp<Device> & device,audio_stream_in_t * stream)144 StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
145     : mDevice(device),
146       mStream(stream),
147       mStreamCommon(new Stream(true /*isInput*/, &stream->common)),
148       mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
149       mEfGroup(nullptr),
150       mStopReadThread(false) {}
151 
~StreamIn()152 StreamIn::~StreamIn() {
153     ATRACE_CALL();
154     close();
155     if (mReadThread.get()) {
156         ATRACE_NAME("mReadThread->join");
157         status_t status = mReadThread->join();
158         ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
159     }
160     if (mEfGroup) {
161         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
162         ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
163     }
164 #if MAJOR_VERSION <= 5
165     mDevice->closeInputStream(mStream);
166 #endif
167     mStream = nullptr;
168 }
169 
170 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
getFrameSize()171 Return<uint64_t> StreamIn::getFrameSize() {
172     return audio_stream_in_frame_size(mStream);
173 }
174 
getFrameCount()175 Return<uint64_t> StreamIn::getFrameCount() {
176     return mStreamCommon->getFrameCount();
177 }
178 
getBufferSize()179 Return<uint64_t> StreamIn::getBufferSize() {
180     return mStreamCommon->getBufferSize();
181 }
182 
183 #if MAJOR_VERSION <= 6
getSampleRate()184 Return<uint32_t> StreamIn::getSampleRate() {
185     return mStreamCommon->getSampleRate();
186 }
187 
188 #if MAJOR_VERSION == 2
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)189 Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
190     return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
191 }
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)192 Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
193     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
194 }
195 #endif
196 
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)197 Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
198                                                 getSupportedChannelMasks_cb _hidl_cb) {
199     return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
200 }
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)201 Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
202                                                getSupportedSampleRates_cb _hidl_cb) {
203     return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
204 }
205 
setSampleRate(uint32_t sampleRateHz)206 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
207     return mStreamCommon->setSampleRate(sampleRateHz);
208 }
209 
getChannelMask()210 Return<AudioChannelBitfield> StreamIn::getChannelMask() {
211     return mStreamCommon->getChannelMask();
212 }
213 
setChannelMask(AudioChannelBitfield mask)214 Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
215     return mStreamCommon->setChannelMask(mask);
216 }
217 
getFormat()218 Return<AudioFormat> StreamIn::getFormat() {
219     return mStreamCommon->getFormat();
220 }
221 
getSupportedFormats(getSupportedFormats_cb _hidl_cb)222 Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
223     return mStreamCommon->getSupportedFormats(_hidl_cb);
224 }
225 
setFormat(AudioFormat format)226 Return<Result> StreamIn::setFormat(AudioFormat format) {
227     return mStreamCommon->setFormat(format);
228 }
229 
230 #else
231 
getSupportedProfiles(getSupportedProfiles_cb _hidl_cb)232 Return<void> StreamIn::getSupportedProfiles(getSupportedProfiles_cb _hidl_cb) {
233     return mStreamCommon->getSupportedProfiles(_hidl_cb);
234 }
235 
setAudioProperties(const AudioConfigBaseOptional & config)236 Return<Result> StreamIn::setAudioProperties(const AudioConfigBaseOptional& config) {
237     return mStreamCommon->setAudioProperties(config);
238 }
239 
240 #endif  // MAJOR_VERSION <= 6
241 
getAudioProperties(getAudioProperties_cb _hidl_cb)242 Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
243     return mStreamCommon->getAudioProperties(_hidl_cb);
244 }
245 
addEffect(uint64_t effectId)246 Return<Result> StreamIn::addEffect(uint64_t effectId) {
247     return mStreamCommon->addEffect(effectId);
248 }
249 
removeEffect(uint64_t effectId)250 Return<Result> StreamIn::removeEffect(uint64_t effectId) {
251     return mStreamCommon->removeEffect(effectId);
252 }
253 
standby()254 Return<Result> StreamIn::standby() {
255     return mStreamCommon->standby();
256 }
257 
setHwAvSync(uint32_t hwAvSync)258 Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
259     return mStreamCommon->setHwAvSync(hwAvSync);
260 }
261 
262 #if MAJOR_VERSION == 2
setConnectedState(const DeviceAddress & address,bool connected)263 Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
264     return mStreamCommon->setConnectedState(address, connected);
265 }
266 
getDevice()267 Return<AudioDevice> StreamIn::getDevice() {
268     return mStreamCommon->getDevice();
269 }
270 
setDevice(const DeviceAddress & address)271 Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
272     return mStreamCommon->setDevice(address);
273 }
274 
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)275 Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
276     return mStreamCommon->getParameters(keys, _hidl_cb);
277 }
278 
setParameters(const hidl_vec<ParameterValue> & parameters)279 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
280     return mStreamCommon->setParameters(parameters);
281 }
282 
debugDump(const hidl_handle & fd)283 Return<void> StreamIn::debugDump(const hidl_handle& fd) {
284     return mStreamCommon->debugDump(fd);
285 }
286 #elif MAJOR_VERSION >= 4
getDevices(getDevices_cb _hidl_cb)287 Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
288     return mStreamCommon->getDevices(_hidl_cb);
289 }
290 
setDevices(const hidl_vec<DeviceAddress> & devices)291 Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
292     return mStreamCommon->setDevices(devices);
293 }
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)294 Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
295                                      const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
296     return mStreamCommon->getParameters(context, keys, _hidl_cb);
297 }
298 
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)299 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
300                                        const hidl_vec<ParameterValue>& parameters) {
301     return mStreamCommon->setParameters(context, parameters);
302 }
303 #endif
304 
start()305 Return<Result> StreamIn::start() {
306     return mStreamMmap->start();
307 }
308 
stop()309 Return<Result> StreamIn::stop() {
310     return mStreamMmap->stop();
311 }
312 
createMmapBuffer(int32_t minSizeFrames,createMmapBuffer_cb _hidl_cb)313 Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
314     return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream),
315                                          _hidl_cb);
316 }
317 
getMmapPosition(getMmapPosition_cb _hidl_cb)318 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
319     return mStreamMmap->getMmapPosition(_hidl_cb);
320 }
321 
close()322 Return<Result> StreamIn::close() {
323     if (mStopReadThread.load(std::memory_order_relaxed)) {  // only this thread writes
324         return Result::INVALID_STATE;
325     }
326     mStopReadThread.store(true, std::memory_order_release);
327     if (mEfGroup) {
328         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
329     }
330 #if MAJOR_VERSION >= 6
331     mDevice->closeInputStream(mStream);
332 #endif
333     return Result::OK;
334 }
335 
336 // Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow.
getAudioSource(getAudioSource_cb _hidl_cb)337 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
338     int halSource;
339     Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
340     AudioSource source = {};
341     if (retval == Result::OK) {
342         retval = Stream::analyzeStatus(
343                 "get_audio_source",
344                 HidlUtils::audioSourceFromHal(static_cast<audio_source_t>(halSource), &source));
345     }
346     _hidl_cb(retval, source);
347     return Void();
348 }
349 
setGain(float gain)350 Return<Result> StreamIn::setGain(float gain) {
351     if (!isGainNormalized(gain)) {
352         ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
353         return Result::INVALID_ARGUMENTS;
354     }
355     return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
356 }
357 
prepareForReading(uint32_t frameSize,uint32_t framesCount,prepareForReading_cb _hidl_cb)358 Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount,
359                                          prepareForReading_cb _hidl_cb) {
360     status_t status;
361 #if MAJOR_VERSION <= 6
362     ThreadInfo threadInfo = {0, 0};
363 #else
364     int32_t threadInfo = 0;
365 #endif
366 
367     // Wrap the _hidl_cb to return an error
368     auto sendError = [&threadInfo, &_hidl_cb](Result result) {
369         _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
370                  threadInfo);
371     };
372 
373     // Create message queues.
374     if (mDataMQ) {
375         ALOGE("the client attempts to call prepareForReading twice");
376         sendError(Result::INVALID_STATE);
377         return Void();
378     }
379     std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
380 
381     // Check frameSize and framesCount
382     if (frameSize == 0 || framesCount == 0) {
383         ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
384         sendError(Result::INVALID_ARGUMENTS);
385         return Void();
386     }
387 
388     if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
389         ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
390               Stream::MAX_BUFFER_SIZE);
391         sendError(Result::INVALID_ARGUMENTS);
392         return Void();
393     }
394     std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
395 
396     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
397     if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
398         ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
399         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
400         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
401         sendError(Result::INVALID_ARGUMENTS);
402         return Void();
403     }
404     EventFlag* tempRawEfGroup{};
405     status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
406     std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
407         tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
408     if (status != OK || !tempElfGroup) {
409         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
410         sendError(Result::INVALID_ARGUMENTS);
411         return Void();
412     }
413 
414     // Create and launch the thread.
415     auto tempReadThread =
416             sp<ReadThread>::make(&mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
417                                  tempStatusMQ.get(), tempElfGroup.get());
418     if (!tempReadThread->init()) {
419         ALOGW("failed to start reader thread: %s", strerror(-status));
420         sendError(Result::INVALID_ARGUMENTS);
421         return Void();
422     }
423     status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO);
424     if (status != OK) {
425         ALOGW("failed to start reader thread: %s", strerror(-status));
426         sendError(Result::INVALID_ARGUMENTS);
427         return Void();
428     }
429 
430     mCommandMQ = std::move(tempCommandMQ);
431     mDataMQ = std::move(tempDataMQ);
432     mStatusMQ = std::move(tempStatusMQ);
433     mReadThread = tempReadThread;
434     mEfGroup = tempElfGroup.release();
435 #if MAJOR_VERSION <= 6
436     threadInfo.pid = getpid();
437     threadInfo.tid = mReadThread->getTid();
438 #else
439     threadInfo = mReadThread->getTid();
440 #endif
441     _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
442              threadInfo);
443     return Void();
444 }
445 
getInputFramesLost()446 Return<uint32_t> StreamIn::getInputFramesLost() {
447     return mStream->get_input_frames_lost(mStream);
448 }
449 
450 // static
getCapturePositionImpl(audio_stream_in_t * stream,uint64_t * frames,uint64_t * time)451 Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
452                                         uint64_t* time) {
453     // HAL may have a stub function, always returning ENOSYS, don't
454     // spam the log in this case.
455     static const std::vector<int> ignoredErrors{ENOSYS};
456     Result retval(Result::NOT_SUPPORTED);
457     if (stream->get_capture_position == NULL) return retval;
458     int64_t halFrames, halTime;
459     retval = Stream::analyzeStatus("get_capture_position",
460                                    stream->get_capture_position(stream, &halFrames, &halTime),
461                                    ignoredErrors);
462     if (retval == Result::OK) {
463         *frames = halFrames;
464         *time = halTime;
465     }
466     return retval;
467 };
468 
getCapturePosition(getCapturePosition_cb _hidl_cb)469 Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
470     uint64_t frames = 0, time = 0;
471     Result retval = getCapturePositionImpl(mStream, &frames, &time);
472     _hidl_cb(retval, frames, time);
473     return Void();
474 }
475 
debug(const hidl_handle & fd,const hidl_vec<hidl_string> & options)476 Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
477     return mStreamCommon->debug(fd, options);
478 }
479 
480 #if MAJOR_VERSION >= 4
doUpdateSinkMetadata(const SinkMetadata & sinkMetadata)481 Result StreamIn::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
482     std::vector<record_track_metadata> halTracks;
483 #if MAJOR_VERSION <= 6
484     (void)CoreUtils::sinkMetadataToHal(sinkMetadata, &halTracks);
485 #else
486     // Validate whether a conversion to V7 is possible. This is needed
487     // to have a consistent behavior of the HAL regardless of the API
488     // version of the legacy HAL (and also to be consistent with openInputStream).
489     std::vector<record_track_metadata_v7> halTracksV7;
490     if (status_t status = CoreUtils::sinkMetadataToHalV7(
491                 sinkMetadata, false /*ignoreNonVendorTags*/, &halTracksV7);
492         status == NO_ERROR) {
493         halTracks.reserve(halTracksV7.size());
494         for (auto metadata_v7 : halTracksV7) {
495             halTracks.push_back(std::move(metadata_v7.base));
496         }
497     } else {
498         return Stream::analyzeStatus("sinkMetadataToHal", status);
499     }
500 #endif  // MAJOR_VERSION <= 6
501     const sink_metadata_t halMetadata = {
502         .track_count = halTracks.size(),
503         .tracks = halTracks.data(),
504     };
505     mStream->update_sink_metadata(mStream, &halMetadata);
506     return Result::OK;
507 }
508 
509 #if MAJOR_VERSION >= 7
doUpdateSinkMetadataV7(const SinkMetadata & sinkMetadata)510 Result StreamIn::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
511     std::vector<record_track_metadata_v7> halTracks;
512     if (status_t status = CoreUtils::sinkMetadataToHalV7(sinkMetadata,
513                                                          false /*ignoreNonVendorTags*/, &halTracks);
514         status != NO_ERROR) {
515         return Stream::analyzeStatus("sinkMetadataToHal", status);
516     }
517     const sink_metadata_v7_t halMetadata = {
518             .track_count = halTracks.size(),
519             .tracks = halTracks.data(),
520     };
521     mStream->update_sink_metadata_v7(mStream, &halMetadata);
522     return Result::OK;
523 }
524 #endif  //  MAJOR_VERSION >= 7
525 
526 #if MAJOR_VERSION <= 6
updateSinkMetadata(const SinkMetadata & sinkMetadata)527 Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
528     if (mStream->update_sink_metadata == nullptr) {
529         return Void();  // not supported by the HAL
530     }
531     (void)doUpdateSinkMetadata(sinkMetadata);
532     return Void();
533 }
534 #elif MAJOR_VERSION >= 7
updateSinkMetadata(const SinkMetadata & sinkMetadata)535 Return<Result> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
536     if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2) {
537         if (mStream->update_sink_metadata == nullptr) {
538             return Result::NOT_SUPPORTED;
539         }
540         return doUpdateSinkMetadata(sinkMetadata);
541     } else {
542         if (mStream->update_sink_metadata_v7 == nullptr) {
543             return Result::NOT_SUPPORTED;
544         }
545         return doUpdateSinkMetadataV7(sinkMetadata);
546     }
547 }
548 #endif
549 
getActiveMicrophones(getActiveMicrophones_cb _hidl_cb)550 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
551     Result retval = Result::NOT_SUPPORTED;
552     size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
553     audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
554 
555     hidl_vec<MicrophoneInfo> microphones;
556     if (mStream->get_active_microphones != NULL &&
557         mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
558         microphones.resize(actual_mics);
559         for (size_t i = 0; i < actual_mics; ++i) {
560             (void)CoreUtils::microphoneInfoFromHal(mic_array[i], &microphones[i]);
561         }
562         retval = Result::OK;
563     }
564 
565     _hidl_cb(retval, microphones);
566     return Void();
567 }
568 #endif
569 
570 #if MAJOR_VERSION >= 5
setMicrophoneDirection(MicrophoneDirection direction)571 Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
572     if (mStream->set_microphone_direction == nullptr) {
573         return Result::NOT_SUPPORTED;
574     }
575     if (!common::utils::isValidHidlEnum(direction)) {
576         ALOGE("%s: Invalid direction %d", __func__, direction);
577         return Result::INVALID_ARGUMENTS;
578     }
579     return Stream::analyzeStatus(
580             "set_microphone_direction",
581             mStream->set_microphone_direction(
582                     mStream, static_cast<audio_microphone_direction_t>(direction)));
583 }
584 
setMicrophoneFieldDimension(float zoom)585 Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
586     if (mStream->set_microphone_field_dimension == nullptr) {
587         return Result::NOT_SUPPORTED;
588     }
589     if (std::isnan(zoom) || zoom < -1 || zoom > 1) {
590         ALOGE("%s: Invalid zoom %f", __func__, zoom);
591         return Result::INVALID_ARGUMENTS;
592     }
593     return Stream::analyzeStatus("set_microphone_field_dimension",
594                                  mStream->set_microphone_field_dimension(mStream, zoom));
595 }
596 
597 #endif
598 
599 }  // namespace implementation
600 }  // namespace CPP_VERSION
601 }  // namespace audio
602 }  // namespace hardware
603 }  // namespace android
604