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/Conversions.h" 21 #include "core/default/Util.h" 22 #include "common/all-versions/HidlSupport.h" 23 24 //#define LOG_NDEBUG 0 25 #define ATRACE_TAG ATRACE_TAG_AUDIO 26 27 #include <android/log.h> 28 #include <hardware/audio.h> 29 #include <utils/Trace.h> 30 #include <memory> 31 #include <cmath> 32 33 namespace android { 34 namespace hardware { 35 namespace audio { 36 namespace CPP_VERSION { 37 namespace implementation { 38 39 namespace { 40 41 class ReadThread : public Thread { 42 public: 43 // ReadThread's lifespan never exceeds StreamIn's lifespan. 44 ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ, 45 StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup) 46 : Thread(false /*canCallJava*/), 47 mStop(stop), 48 mStream(stream), 49 mCommandMQ(commandMQ), 50 mDataMQ(dataMQ), 51 mStatusMQ(statusMQ), 52 mEfGroup(efGroup), 53 mBuffer(nullptr) {} 54 bool init() { 55 mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]); 56 return mBuffer != nullptr; 57 } 58 virtual ~ReadThread() {} 59 60 private: 61 std::atomic<bool>* mStop; 62 audio_stream_in_t* mStream; 63 StreamIn::CommandMQ* mCommandMQ; 64 StreamIn::DataMQ* mDataMQ; 65 StreamIn::StatusMQ* mStatusMQ; 66 EventFlag* mEfGroup; 67 std::unique_ptr<uint8_t[]> mBuffer; 68 IStreamIn::ReadParameters mParameters; 69 IStreamIn::ReadStatus mStatus; 70 71 bool threadLoop() override; 72 73 void doGetCapturePosition(); 74 void doRead(); 75 }; 76 77 void ReadThread::doRead() { 78 size_t availableToWrite = mDataMQ->availableToWrite(); 79 size_t requestedToRead = mParameters.params.read; 80 if (requestedToRead > availableToWrite) { 81 ALOGW( 82 "truncating read data from %d to %d due to insufficient data queue " 83 "space", 84 (int32_t)requestedToRead, (int32_t)availableToWrite); 85 requestedToRead = availableToWrite; 86 } 87 ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead); 88 mStatus.retval = Result::OK; 89 if (readResult >= 0) { 90 mStatus.reply.read = readResult; 91 if (!mDataMQ->write(&mBuffer[0], readResult)) { 92 ALOGW("data message queue write failed"); 93 } 94 } else { 95 mStatus.retval = Stream::analyzeStatus("read", readResult); 96 } 97 } 98 99 void ReadThread::doGetCapturePosition() { 100 mStatus.retval = StreamIn::getCapturePositionImpl( 101 mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time); 102 } 103 104 bool ReadThread::threadLoop() { 105 // This implementation doesn't return control back to the Thread until it 106 // decides to stop, 107 // as the Thread uses mutexes, and this can lead to priority inversion. 108 while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { 109 uint32_t efState = 0; 110 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState); 111 if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) { 112 continue; // Nothing to do. 113 } 114 if (!mCommandMQ->read(&mParameters)) { 115 continue; // Nothing to do. 116 } 117 mStatus.replyTo = mParameters.command; 118 switch (mParameters.command) { 119 case IStreamIn::ReadCommand::READ: 120 doRead(); 121 break; 122 case IStreamIn::ReadCommand::GET_CAPTURE_POSITION: 123 doGetCapturePosition(); 124 break; 125 default: 126 ALOGE("Unknown read thread command code %d", mParameters.command); 127 mStatus.retval = Result::NOT_SUPPORTED; 128 break; 129 } 130 if (!mStatusMQ->write(&mStatus)) { 131 ALOGW("status message queue write failed"); 132 } 133 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); 134 } 135 136 return false; 137 } 138 139 } // namespace 140 141 StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream) 142 : mIsClosed(false), 143 mDevice(device), 144 mStream(stream), 145 mStreamCommon(new Stream(&stream->common)), 146 mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)), 147 mEfGroup(nullptr), 148 mStopReadThread(false) {} 149 150 StreamIn::~StreamIn() { 151 ATRACE_CALL(); 152 close(); 153 if (mReadThread.get()) { 154 ATRACE_NAME("mReadThread->join"); 155 status_t status = mReadThread->join(); 156 ALOGE_IF(status, "read thread exit error: %s", strerror(-status)); 157 } 158 if (mEfGroup) { 159 status_t status = EventFlag::deleteEventFlag(&mEfGroup); 160 ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status)); 161 } 162 mDevice->closeInputStream(mStream); 163 mStream = nullptr; 164 } 165 166 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow. 167 Return<uint64_t> StreamIn::getFrameSize() { 168 return audio_stream_in_frame_size(mStream); 169 } 170 171 Return<uint64_t> StreamIn::getFrameCount() { 172 return mStreamCommon->getFrameCount(); 173 } 174 175 Return<uint64_t> StreamIn::getBufferSize() { 176 return mStreamCommon->getBufferSize(); 177 } 178 179 Return<uint32_t> StreamIn::getSampleRate() { 180 return mStreamCommon->getSampleRate(); 181 } 182 183 #if MAJOR_VERSION == 2 184 Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { 185 return mStreamCommon->getSupportedChannelMasks(_hidl_cb); 186 } 187 Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { 188 return mStreamCommon->getSupportedSampleRates(_hidl_cb); 189 } 190 #endif 191 192 Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format, 193 getSupportedChannelMasks_cb _hidl_cb) { 194 return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); 195 } 196 Return<void> StreamIn::getSupportedSampleRates(AudioFormat format, 197 getSupportedSampleRates_cb _hidl_cb) { 198 return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); 199 } 200 201 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) { 202 return mStreamCommon->setSampleRate(sampleRateHz); 203 } 204 205 Return<AudioChannelBitfield> StreamIn::getChannelMask() { 206 return mStreamCommon->getChannelMask(); 207 } 208 209 Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) { 210 return mStreamCommon->setChannelMask(mask); 211 } 212 213 Return<AudioFormat> StreamIn::getFormat() { 214 return mStreamCommon->getFormat(); 215 } 216 217 Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { 218 return mStreamCommon->getSupportedFormats(_hidl_cb); 219 } 220 221 Return<Result> StreamIn::setFormat(AudioFormat format) { 222 return mStreamCommon->setFormat(format); 223 } 224 225 Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) { 226 return mStreamCommon->getAudioProperties(_hidl_cb); 227 } 228 229 Return<Result> StreamIn::addEffect(uint64_t effectId) { 230 return mStreamCommon->addEffect(effectId); 231 } 232 233 Return<Result> StreamIn::removeEffect(uint64_t effectId) { 234 return mStreamCommon->removeEffect(effectId); 235 } 236 237 Return<Result> StreamIn::standby() { 238 return mStreamCommon->standby(); 239 } 240 241 Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) { 242 return mStreamCommon->setHwAvSync(hwAvSync); 243 } 244 245 #if MAJOR_VERSION == 2 246 Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) { 247 return mStreamCommon->setConnectedState(address, connected); 248 } 249 250 Return<AudioDevice> StreamIn::getDevice() { 251 return mStreamCommon->getDevice(); 252 } 253 254 Return<Result> StreamIn::setDevice(const DeviceAddress& address) { 255 return mStreamCommon->setDevice(address); 256 } 257 258 Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 259 return mStreamCommon->getParameters(keys, _hidl_cb); 260 } 261 262 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) { 263 return mStreamCommon->setParameters(parameters); 264 } 265 266 Return<void> StreamIn::debugDump(const hidl_handle& fd) { 267 return mStreamCommon->debugDump(fd); 268 } 269 #elif MAJOR_VERSION >= 4 270 Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) { 271 return mStreamCommon->getDevices(_hidl_cb); 272 } 273 274 Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) { 275 return mStreamCommon->setDevices(devices); 276 } 277 Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context, 278 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 279 return mStreamCommon->getParameters(context, keys, _hidl_cb); 280 } 281 282 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context, 283 const hidl_vec<ParameterValue>& parameters) { 284 return mStreamCommon->setParameters(context, parameters); 285 } 286 #endif 287 288 Return<Result> StreamIn::start() { 289 return mStreamMmap->start(); 290 } 291 292 Return<Result> StreamIn::stop() { 293 return mStreamMmap->stop(); 294 } 295 296 Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { 297 return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream), 298 _hidl_cb); 299 } 300 301 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) { 302 return mStreamMmap->getMmapPosition(_hidl_cb); 303 } 304 305 Return<Result> StreamIn::close() { 306 if (mIsClosed) return Result::INVALID_STATE; 307 mIsClosed = true; 308 if (mReadThread.get()) { 309 mStopReadThread.store(true, std::memory_order_release); 310 } 311 if (mEfGroup) { 312 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)); 313 } 314 return Result::OK; 315 } 316 317 // Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow. 318 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) { 319 int halSource; 320 Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource); 321 AudioSource source(AudioSource::DEFAULT); 322 if (retval == Result::OK) { 323 source = AudioSource(halSource); 324 } 325 _hidl_cb(retval, source); 326 return Void(); 327 } 328 329 Return<Result> StreamIn::setGain(float gain) { 330 if (!isGainNormalized(gain)) { 331 ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain); 332 return Result::INVALID_ARGUMENTS; 333 } 334 return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain)); 335 } 336 337 Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount, 338 prepareForReading_cb _hidl_cb) { 339 status_t status; 340 ThreadInfo threadInfo = {0, 0}; 341 342 // Wrap the _hidl_cb to return an error 343 auto sendError = [&threadInfo, &_hidl_cb](Result result) { 344 _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), 345 threadInfo); 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 417 Return<uint32_t> StreamIn::getInputFramesLost() { 418 return mStream->get_input_frames_lost(mStream); 419 } 420 421 // static 422 Result 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 440 Return<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 447 Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) { 448 return mStreamCommon->debug(fd, options); 449 } 450 451 #if MAJOR_VERSION >= 4 452 Return<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 record_track_metadata halTrackMetadata = { 460 .source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain}; 461 #if MAJOR_VERSION >= 5 462 if (metadata.destination.getDiscriminator() == 463 RecordTrackMetadata::Destination::hidl_discriminator::device) { 464 halTrackMetadata.dest_device = 465 static_cast<audio_devices_t>(metadata.destination.device().device); 466 strncpy(halTrackMetadata.dest_device_address, 467 deviceAddressToHal(metadata.destination.device()).c_str(), 468 AUDIO_DEVICE_MAX_ADDRESS_LEN); 469 } 470 #endif 471 halTracks.push_back(halTrackMetadata); 472 } 473 const sink_metadata_t halMetadata = { 474 .track_count = halTracks.size(), 475 .tracks = halTracks.data(), 476 }; 477 mStream->update_sink_metadata(mStream, &halMetadata); 478 return Void(); 479 } 480 481 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) { 482 Result retval = Result::NOT_SUPPORTED; 483 size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT; 484 audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT]; 485 486 hidl_vec<MicrophoneInfo> microphones; 487 if (mStream->get_active_microphones != NULL && 488 mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) { 489 microphones.resize(actual_mics); 490 for (size_t i = 0; i < actual_mics; ++i) { 491 halToMicrophoneCharacteristics(µphones[i], mic_array[i]); 492 } 493 retval = Result::OK; 494 } 495 496 _hidl_cb(retval, microphones); 497 return Void(); 498 } 499 #endif 500 501 #if MAJOR_VERSION >= 5 502 Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) { 503 if (mStream->set_microphone_direction == nullptr) { 504 return Result::NOT_SUPPORTED; 505 } 506 if (!common::utils::isValidHidlEnum(direction)) { 507 ALOGE("%s: Invalid direction %d", __func__, direction); 508 return Result::INVALID_ARGUMENTS; 509 } 510 return Stream::analyzeStatus( 511 "set_microphone_direction", 512 mStream->set_microphone_direction( 513 mStream, static_cast<audio_microphone_direction_t>(direction))); 514 } 515 516 Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) { 517 if (mStream->set_microphone_field_dimension == nullptr) { 518 return Result::NOT_SUPPORTED; 519 } 520 if (std::isnan(zoom) || zoom < -1 || zoom > 1) { 521 ALOGE("%s: Invalid zoom %f", __func__, zoom); 522 return Result::INVALID_ARGUMENTS; 523 } 524 return Stream::analyzeStatus("set_microphone_field_dimension", 525 mStream->set_microphone_field_dimension(mStream, zoom)); 526 } 527 528 #endif 529 530 } // namespace implementation 531 } // namespace CPP_VERSION 532 } // namespace audio 533 } // namespace hardware 534 } // namespace android 535