1/* 2 * Copyright (C) 2016 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#include <common/all-versions/IncludeGuard.h> 18 19//#define LOG_NDEBUG 0 20#define ATRACE_TAG ATRACE_TAG_AUDIO 21 22#include <android/log.h> 23#include <hardware/audio.h> 24#include <utils/Trace.h> 25#include <memory> 26 27using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits; 28#include "Conversions.h" 29 30namespace android { 31namespace hardware { 32namespace audio { 33namespace AUDIO_HAL_VERSION { 34namespace implementation { 35 36using ::android::hardware::audio::common::AUDIO_HAL_VERSION::ThreadInfo; 37 38namespace { 39 40class ReadThread : public Thread { 41 public: 42 // ReadThread's lifespan never exceeds StreamIn's lifespan. 43 ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ, 44 StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup) 45 : Thread(false /*canCallJava*/), 46 mStop(stop), 47 mStream(stream), 48 mCommandMQ(commandMQ), 49 mDataMQ(dataMQ), 50 mStatusMQ(statusMQ), 51 mEfGroup(efGroup), 52 mBuffer(nullptr) {} 53 bool init() { 54 mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]); 55 return mBuffer != nullptr; 56 } 57 virtual ~ReadThread() {} 58 59 private: 60 std::atomic<bool>* mStop; 61 audio_stream_in_t* mStream; 62 StreamIn::CommandMQ* mCommandMQ; 63 StreamIn::DataMQ* mDataMQ; 64 StreamIn::StatusMQ* mStatusMQ; 65 EventFlag* mEfGroup; 66 std::unique_ptr<uint8_t[]> mBuffer; 67 IStreamIn::ReadParameters mParameters; 68 IStreamIn::ReadStatus mStatus; 69 70 bool threadLoop() override; 71 72 void doGetCapturePosition(); 73 void doRead(); 74}; 75 76void ReadThread::doRead() { 77 size_t availableToWrite = mDataMQ->availableToWrite(); 78 size_t requestedToRead = mParameters.params.read; 79 if (requestedToRead > availableToWrite) { 80 ALOGW( 81 "truncating read data from %d to %d due to insufficient data queue " 82 "space", 83 (int32_t)requestedToRead, (int32_t)availableToWrite); 84 requestedToRead = availableToWrite; 85 } 86 ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead); 87 mStatus.retval = Result::OK; 88 if (readResult >= 0) { 89 mStatus.reply.read = readResult; 90 if (!mDataMQ->write(&mBuffer[0], readResult)) { 91 ALOGW("data message queue write failed"); 92 } 93 } else { 94 mStatus.retval = Stream::analyzeStatus("read", readResult); 95 } 96} 97 98void ReadThread::doGetCapturePosition() { 99 mStatus.retval = StreamIn::getCapturePositionImpl( 100 mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time); 101} 102 103bool ReadThread::threadLoop() { 104 // This implementation doesn't return control back to the Thread until it 105 // decides to stop, 106 // as the Thread uses mutexes, and this can lead to priority inversion. 107 while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { 108 uint32_t efState = 0; 109 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState); 110 if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) { 111 continue; // Nothing to do. 112 } 113 if (!mCommandMQ->read(&mParameters)) { 114 continue; // Nothing to do. 115 } 116 mStatus.replyTo = mParameters.command; 117 switch (mParameters.command) { 118 case IStreamIn::ReadCommand::READ: 119 doRead(); 120 break; 121 case IStreamIn::ReadCommand::GET_CAPTURE_POSITION: 122 doGetCapturePosition(); 123 break; 124 default: 125 ALOGE("Unknown read thread command code %d", mParameters.command); 126 mStatus.retval = Result::NOT_SUPPORTED; 127 break; 128 } 129 if (!mStatusMQ->write(&mStatus)) { 130 ALOGW("status message queue write failed"); 131 } 132 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); 133 } 134 135 return false; 136} 137 138} // namespace 139 140StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream) 141 : mIsClosed(false), 142 mDevice(device), 143 mStream(stream), 144 mStreamCommon(new Stream(&stream->common)), 145 mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)), 146 mEfGroup(nullptr), 147 mStopReadThread(false) {} 148 149StreamIn::~StreamIn() { 150 ATRACE_CALL(); 151 close(); 152 if (mReadThread.get()) { 153 ATRACE_NAME("mReadThread->join"); 154 status_t status = mReadThread->join(); 155 ALOGE_IF(status, "read thread exit error: %s", strerror(-status)); 156 } 157 if (mEfGroup) { 158 status_t status = EventFlag::deleteEventFlag(&mEfGroup); 159 ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status)); 160 } 161 mDevice->closeInputStream(mStream); 162 mStream = nullptr; 163} 164 165// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStream follow. 166Return<uint64_t> StreamIn::getFrameSize() { 167 return audio_stream_in_frame_size(mStream); 168} 169 170Return<uint64_t> StreamIn::getFrameCount() { 171 return mStreamCommon->getFrameCount(); 172} 173 174Return<uint64_t> StreamIn::getBufferSize() { 175 return mStreamCommon->getBufferSize(); 176} 177 178Return<uint32_t> StreamIn::getSampleRate() { 179 return mStreamCommon->getSampleRate(); 180} 181 182#ifdef AUDIO_HAL_VERSION_2_0 183Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { 184 return mStreamCommon->getSupportedChannelMasks(_hidl_cb); 185} 186Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { 187 return mStreamCommon->getSupportedSampleRates(_hidl_cb); 188} 189#endif 190 191Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format, 192 getSupportedChannelMasks_cb _hidl_cb) { 193 return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); 194} 195Return<void> StreamIn::getSupportedSampleRates(AudioFormat format, 196 getSupportedSampleRates_cb _hidl_cb) { 197 return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); 198} 199 200Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) { 201 return mStreamCommon->setSampleRate(sampleRateHz); 202} 203 204Return<AudioChannelBitfield> StreamIn::getChannelMask() { 205 return mStreamCommon->getChannelMask(); 206} 207 208Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) { 209 return mStreamCommon->setChannelMask(mask); 210} 211 212Return<AudioFormat> StreamIn::getFormat() { 213 return mStreamCommon->getFormat(); 214} 215 216Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { 217 return mStreamCommon->getSupportedFormats(_hidl_cb); 218} 219 220Return<Result> StreamIn::setFormat(AudioFormat format) { 221 return mStreamCommon->setFormat(format); 222} 223 224Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) { 225 return mStreamCommon->getAudioProperties(_hidl_cb); 226} 227 228Return<Result> StreamIn::addEffect(uint64_t effectId) { 229 return mStreamCommon->addEffect(effectId); 230} 231 232Return<Result> StreamIn::removeEffect(uint64_t effectId) { 233 return mStreamCommon->removeEffect(effectId); 234} 235 236Return<Result> StreamIn::standby() { 237 return mStreamCommon->standby(); 238} 239 240Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) { 241 return mStreamCommon->setHwAvSync(hwAvSync); 242} 243 244#ifdef AUDIO_HAL_VERSION_2_0 245Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) { 246 return mStreamCommon->setConnectedState(address, connected); 247} 248 249Return<AudioDevice> StreamIn::getDevice() { 250 return mStreamCommon->getDevice(); 251} 252 253Return<Result> StreamIn::setDevice(const DeviceAddress& address) { 254 return mStreamCommon->setDevice(address); 255} 256 257Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 258 return mStreamCommon->getParameters(keys, _hidl_cb); 259} 260 261Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) { 262 return mStreamCommon->setParameters(parameters); 263} 264 265Return<void> StreamIn::debugDump(const hidl_handle& fd) { 266 return mStreamCommon->debugDump(fd); 267} 268#elif defined(AUDIO_HAL_VERSION_4_0) 269Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) { 270 return mStreamCommon->getDevices(_hidl_cb); 271} 272 273Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) { 274 return mStreamCommon->setDevices(devices); 275} 276Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context, 277 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 278 return mStreamCommon->getParameters(context, keys, _hidl_cb); 279} 280 281Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context, 282 const hidl_vec<ParameterValue>& parameters) { 283 return mStreamCommon->setParameters(context, parameters); 284} 285#endif 286 287Return<Result> StreamIn::start() { 288 return mStreamMmap->start(); 289} 290 291Return<Result> StreamIn::stop() { 292 return mStreamMmap->stop(); 293} 294 295Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { 296 return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream), 297 _hidl_cb); 298} 299 300Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) { 301 return mStreamMmap->getMmapPosition(_hidl_cb); 302} 303 304Return<Result> StreamIn::close() { 305 if (mIsClosed) return Result::INVALID_STATE; 306 mIsClosed = true; 307 if (mReadThread.get()) { 308 mStopReadThread.store(true, std::memory_order_release); 309 } 310 if (mEfGroup) { 311 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)); 312 } 313 return Result::OK; 314} 315 316// Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow. 317Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) { 318 int halSource; 319 Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource); 320 AudioSource source(AudioSource::DEFAULT); 321 if (retval == Result::OK) { 322 source = AudioSource(halSource); 323 } 324 _hidl_cb(retval, source); 325 return Void(); 326} 327 328Return<Result> StreamIn::setGain(float gain) { 329 if (!isGainNormalized(gain)) { 330 ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain); 331 return Result::INVALID_ARGUMENTS; 332 } 333 return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain)); 334} 335 336Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount, 337 prepareForReading_cb _hidl_cb) { 338 status_t status; 339 ThreadInfo threadInfo = {0, 0}; 340 341 // Wrap the _hidl_cb to return an error 342 auto sendError = [&threadInfo, &_hidl_cb](Result result) { 343 _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), 344 threadInfo); 345 346 }; 347 348 // Create message queues. 349 if (mDataMQ) { 350 ALOGE("the client attempts to call prepareForReading twice"); 351 sendError(Result::INVALID_STATE); 352 return Void(); 353 } 354 std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1)); 355 356 // Check frameSize and framesCount 357 if (frameSize == 0 || framesCount == 0) { 358 ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount); 359 sendError(Result::INVALID_ARGUMENTS); 360 return Void(); 361 } 362 363 if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) { 364 ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount, 365 Stream::MAX_BUFFER_SIZE); 366 sendError(Result::INVALID_ARGUMENTS); 367 return Void(); 368 } 369 std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */)); 370 371 std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1)); 372 if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) { 373 ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid"); 374 ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid"); 375 ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); 376 sendError(Result::INVALID_ARGUMENTS); 377 return Void(); 378 } 379 EventFlag* tempRawEfGroup{}; 380 status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup); 381 std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup( 382 tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); }); 383 if (status != OK || !tempElfGroup) { 384 ALOGE("failed creating event flag for data MQ: %s", strerror(-status)); 385 sendError(Result::INVALID_ARGUMENTS); 386 return Void(); 387 } 388 389 // Create and launch the thread. 390 auto tempReadThread = 391 std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(), 392 tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get()); 393 if (!tempReadThread->init()) { 394 ALOGW("failed to start reader thread: %s", strerror(-status)); 395 sendError(Result::INVALID_ARGUMENTS); 396 return Void(); 397 } 398 status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO); 399 if (status != OK) { 400 ALOGW("failed to start reader thread: %s", strerror(-status)); 401 sendError(Result::INVALID_ARGUMENTS); 402 return Void(); 403 } 404 405 mCommandMQ = std::move(tempCommandMQ); 406 mDataMQ = std::move(tempDataMQ); 407 mStatusMQ = std::move(tempStatusMQ); 408 mReadThread = tempReadThread.release(); 409 mEfGroup = tempElfGroup.release(); 410 threadInfo.pid = getpid(); 411 threadInfo.tid = mReadThread->getTid(); 412 _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(), 413 threadInfo); 414 return Void(); 415} 416 417Return<uint32_t> StreamIn::getInputFramesLost() { 418 return mStream->get_input_frames_lost(mStream); 419} 420 421// static 422Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames, 423 uint64_t* time) { 424 // HAL may have a stub function, always returning ENOSYS, don't 425 // spam the log in this case. 426 static const std::vector<int> ignoredErrors{ENOSYS}; 427 Result retval(Result::NOT_SUPPORTED); 428 if (stream->get_capture_position == NULL) return retval; 429 int64_t halFrames, halTime; 430 retval = Stream::analyzeStatus("get_capture_position", 431 stream->get_capture_position(stream, &halFrames, &halTime), 432 ignoredErrors); 433 if (retval == Result::OK) { 434 *frames = halFrames; 435 *time = halTime; 436 } 437 return retval; 438}; 439 440Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) { 441 uint64_t frames = 0, time = 0; 442 Result retval = getCapturePositionImpl(mStream, &frames, &time); 443 _hidl_cb(retval, frames, time); 444 return Void(); 445} 446 447Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) { 448 return mStreamCommon->debug(fd, options); 449} 450 451#ifdef AUDIO_HAL_VERSION_4_0 452Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) { 453 if (mStream->update_sink_metadata == nullptr) { 454 return Void(); // not supported by the HAL 455 } 456 std::vector<record_track_metadata> halTracks; 457 halTracks.reserve(sinkMetadata.tracks.size()); 458 for (auto& metadata : sinkMetadata.tracks) { 459 halTracks.push_back( 460 {.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain}); 461 } 462 const sink_metadata_t halMetadata = { 463 .track_count = halTracks.size(), .tracks = halTracks.data(), 464 }; 465 mStream->update_sink_metadata(mStream, &halMetadata); 466 return Void(); 467} 468 469Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) { 470 Result retval = Result::NOT_SUPPORTED; 471 size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT; 472 audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT]; 473 474 hidl_vec<MicrophoneInfo> microphones; 475 if (mStream->get_active_microphones != NULL && 476 mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) { 477 microphones.resize(actual_mics); 478 for (size_t i = 0; i < actual_mics; ++i) { 479 halToMicrophoneCharacteristics(µphones[i], mic_array[i]); 480 } 481 retval = Result::OK; 482 } 483 484 _hidl_cb(retval, microphones); 485 return Void(); 486} 487#endif 488 489} // namespace implementation 490} // namespace AUDIO_HAL_VERSION 491} // namespace audio 492} // namespace hardware 493} // namespace android 494