1 /* 2 ** 3 ** Copyright 2014, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 19 #define LOG_TAG "AudioFlinger::PatchPanel" 20 //#define LOG_NDEBUG 0 21 22 #include "Configuration.h" 23 #include <utils/Log.h> 24 #include <audio_utils/primitives.h> 25 26 #include "AudioFlinger.h" 27 #include <media/AudioParameter.h> 28 #include <media/PatchBuilder.h> 29 #include <mediautils/ServiceUtilities.h> 30 31 // ---------------------------------------------------------------------------- 32 33 // Note: the following macro is used for extremely verbose logging message. In 34 // order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to 35 // 0; but one side effect of this is to turn all LOGV's as well. Some messages 36 // are so verbose that we want to suppress them even when we have ALOG_ASSERT 37 // turned on. Do not uncomment the #def below unless you really know what you 38 // are doing and want to see all of the extremely verbose messages. 39 //#define VERY_VERY_VERBOSE_LOGGING 40 #ifdef VERY_VERY_VERBOSE_LOGGING 41 #define ALOGVV ALOGV 42 #else 43 #define ALOGVV(a...) do { } while(0) 44 #endif 45 46 namespace android { 47 48 /* List connected audio ports and their attributes */ 49 status_t AudioFlinger::listAudioPorts(unsigned int *num_ports, 50 struct audio_port *ports) 51 { 52 Mutex::Autolock _l(mLock); 53 return mPatchPanel.listAudioPorts(num_ports, ports); 54 } 55 56 /* Get supported attributes for a given audio port */ 57 status_t AudioFlinger::getAudioPort(struct audio_port *port) 58 { 59 Mutex::Autolock _l(mLock); 60 return mPatchPanel.getAudioPort(port); 61 } 62 63 /* Connect a patch between several source and sink ports */ 64 status_t AudioFlinger::createAudioPatch(const struct audio_patch *patch, 65 audio_patch_handle_t *handle) 66 { 67 Mutex::Autolock _l(mLock); 68 return mPatchPanel.createAudioPatch(patch, handle); 69 } 70 71 /* Disconnect a patch */ 72 status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle) 73 { 74 Mutex::Autolock _l(mLock); 75 return mPatchPanel.releaseAudioPatch(handle); 76 } 77 78 /* List connected audio ports and they attributes */ 79 status_t AudioFlinger::listAudioPatches(unsigned int *num_patches, 80 struct audio_patch *patches) 81 { 82 Mutex::Autolock _l(mLock); 83 return mPatchPanel.listAudioPatches(num_patches, patches); 84 } 85 86 status_t AudioFlinger::PatchPanel::SoftwarePatch::getLatencyMs_l(double *latencyMs) const 87 { 88 const auto& iter = mPatchPanel.mPatches.find(mPatchHandle); 89 if (iter != mPatchPanel.mPatches.end()) { 90 return iter->second.getLatencyMs(latencyMs); 91 } else { 92 return BAD_VALUE; 93 } 94 } 95 96 /* List connected audio ports and their attributes */ 97 status_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused, 98 struct audio_port *ports __unused) 99 { 100 ALOGV(__func__); 101 return NO_ERROR; 102 } 103 104 /* Get supported attributes for a given audio port */ 105 status_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port *port __unused) 106 { 107 ALOGV(__func__); 108 return NO_ERROR; 109 } 110 111 /* Connect a patch between several source and sink ports */ 112 status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch, 113 audio_patch_handle_t *handle) 114 { 115 if (handle == NULL || patch == NULL) { 116 return BAD_VALUE; 117 } 118 ALOGV("%s() num_sources %d num_sinks %d handle %d", 119 __func__, patch->num_sources, patch->num_sinks, *handle); 120 status_t status = NO_ERROR; 121 audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE; 122 123 if (!audio_patch_is_valid(patch) || (patch->num_sinks == 0 && patch->num_sources != 2)) { 124 return BAD_VALUE; 125 } 126 // limit number of sources to 1 for now or 2 sources for special cross hw module case. 127 // only the audio policy manager can request a patch creation with 2 sources. 128 if (patch->num_sources > 2) { 129 return INVALID_OPERATION; 130 } 131 132 if (*handle != AUDIO_PATCH_HANDLE_NONE) { 133 auto iter = mPatches.find(*handle); 134 if (iter != mPatches.end()) { 135 ALOGV("%s() removing patch handle %d", __func__, *handle); 136 Patch &removedPatch = iter->second; 137 // free resources owned by the removed patch if applicable 138 // 1) if a software patch is present, release the playback and capture threads and 139 // tracks created. This will also release the corresponding audio HAL patches 140 if (removedPatch.isSoftware()) { 141 removedPatch.clearConnections(this); 142 } 143 // 2) if the new patch and old patch source or sink are devices from different 144 // hw modules, clear the audio HAL patches now because they will not be updated 145 // by call to create_audio_patch() below which will happen on a different HW module 146 if (removedPatch.mHalHandle != AUDIO_PATCH_HANDLE_NONE) { 147 audio_module_handle_t hwModule = AUDIO_MODULE_HANDLE_NONE; 148 const struct audio_patch &oldPatch = removedPatch.mAudioPatch; 149 if (oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE && 150 (patch->sources[0].type != AUDIO_PORT_TYPE_DEVICE || 151 oldPatch.sources[0].ext.device.hw_module != 152 patch->sources[0].ext.device.hw_module)) { 153 hwModule = oldPatch.sources[0].ext.device.hw_module; 154 } else if (patch->num_sinks == 0 || 155 (oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE && 156 (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE || 157 oldPatch.sinks[0].ext.device.hw_module != 158 patch->sinks[0].ext.device.hw_module))) { 159 // Note on (patch->num_sinks == 0): this situation should not happen as 160 // these special patches are only created by the policy manager but just 161 // in case, systematically clear the HAL patch. 162 // Note that removedPatch.mAudioPatch.num_sinks cannot be 0 here because 163 // removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case. 164 hwModule = oldPatch.sinks[0].ext.device.hw_module; 165 } 166 sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule); 167 if (hwDevice != 0) { 168 hwDevice->releaseAudioPatch(removedPatch.mHalHandle); 169 } 170 } 171 mPatches.erase(iter); 172 removeSoftwarePatchFromInsertedModules(*handle); 173 } 174 } 175 176 Patch newPatch{*patch}; 177 audio_module_handle_t insertedModule = AUDIO_MODULE_HANDLE_NONE; 178 179 switch (patch->sources[0].type) { 180 case AUDIO_PORT_TYPE_DEVICE: { 181 audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 182 AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(srcModule); 183 if (!audioHwDevice) { 184 status = BAD_VALUE; 185 goto exit; 186 } 187 for (unsigned int i = 0; i < patch->num_sinks; i++) { 188 // support only one sink if connection to a mix or across HW modules 189 if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || 190 (patch->sinks[i].type == AUDIO_PORT_TYPE_DEVICE && 191 patch->sinks[i].ext.device.hw_module != srcModule)) && 192 patch->num_sinks > 1) { 193 ALOGW("%s() multiple sinks for mix or across modules not supported", __func__); 194 status = INVALID_OPERATION; 195 goto exit; 196 } 197 // reject connection to different sink types 198 if (patch->sinks[i].type != patch->sinks[0].type) { 199 ALOGW("%s() different sink types in same patch not supported", __func__); 200 status = BAD_VALUE; 201 goto exit; 202 } 203 } 204 205 // manage patches requiring a software bridge 206 // - special patch request with 2 sources (reuse one existing output mix) OR 207 // - Device to device AND 208 // - source HW module != destination HW module OR 209 // - audio HAL does not support audio patches creation 210 if ((patch->num_sources == 2) || 211 ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) && 212 ((patch->sinks[0].ext.device.hw_module != srcModule) || 213 !audioHwDevice->supportsAudioPatches()))) { 214 audio_devices_t outputDevice = patch->sinks[0].ext.device.type; 215 String8 outputDeviceAddress = String8(patch->sinks[0].ext.device.address); 216 if (patch->num_sources == 2) { 217 if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX || 218 (patch->num_sinks != 0 && patch->sinks[0].ext.device.hw_module != 219 patch->sources[1].ext.mix.hw_module)) { 220 ALOGW("%s() invalid source combination", __func__); 221 status = INVALID_OPERATION; 222 goto exit; 223 } 224 225 sp<ThreadBase> thread = 226 mAudioFlinger.checkPlaybackThread_l(patch->sources[1].ext.mix.handle); 227 if (thread == 0) { 228 ALOGW("%s() cannot get playback thread", __func__); 229 status = INVALID_OPERATION; 230 goto exit; 231 } 232 // existing playback thread is reused, so it is not closed when patch is cleared 233 newPatch.mPlayback.setThread( 234 reinterpret_cast<PlaybackThread*>(thread.get()), false /*closeThread*/); 235 } else { 236 audio_config_t config = AUDIO_CONFIG_INITIALIZER; 237 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 238 audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE; 239 if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 240 config.sample_rate = patch->sinks[0].sample_rate; 241 } 242 if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 243 config.channel_mask = patch->sinks[0].channel_mask; 244 } 245 if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FORMAT) { 246 config.format = patch->sinks[0].format; 247 } 248 if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) { 249 flags = patch->sinks[0].flags.output; 250 } 251 sp<ThreadBase> thread = mAudioFlinger.openOutput_l( 252 patch->sinks[0].ext.device.hw_module, 253 &output, 254 &config, 255 outputDevice, 256 outputDeviceAddress, 257 flags); 258 ALOGV("mAudioFlinger.openOutput_l() returned %p", thread.get()); 259 if (thread == 0) { 260 status = NO_MEMORY; 261 goto exit; 262 } 263 newPatch.mPlayback.setThread(reinterpret_cast<PlaybackThread*>(thread.get())); 264 } 265 audio_devices_t device = patch->sources[0].ext.device.type; 266 String8 address = String8(patch->sources[0].ext.device.address); 267 audio_config_t config = AUDIO_CONFIG_INITIALIZER; 268 // open input stream with source device audio properties if provided or 269 // default to peer output stream properties otherwise. 270 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 271 config.sample_rate = patch->sources[0].sample_rate; 272 } else { 273 config.sample_rate = newPatch.mPlayback.thread()->sampleRate(); 274 } 275 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 276 config.channel_mask = patch->sources[0].channel_mask; 277 } else { 278 config.channel_mask = audio_channel_in_mask_from_count( 279 newPatch.mPlayback.thread()->channelCount()); 280 } 281 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FORMAT) { 282 config.format = patch->sources[0].format; 283 } else { 284 config.format = newPatch.mPlayback.thread()->format(); 285 } 286 audio_input_flags_t flags = 287 patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? 288 patch->sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; 289 audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 290 sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule, 291 &input, 292 &config, 293 device, 294 address, 295 AUDIO_SOURCE_MIC, 296 flags, 297 outputDevice, 298 outputDeviceAddress); 299 ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x", 300 thread.get(), config.channel_mask); 301 if (thread == 0) { 302 status = NO_MEMORY; 303 goto exit; 304 } 305 newPatch.mRecord.setThread(reinterpret_cast<RecordThread*>(thread.get())); 306 status = newPatch.createConnections(this); 307 if (status != NO_ERROR) { 308 goto exit; 309 } 310 if (audioHwDevice->isInsert()) { 311 insertedModule = audioHwDevice->handle(); 312 } 313 } else { 314 if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 315 sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l( 316 patch->sinks[0].ext.mix.handle); 317 if (thread == 0) { 318 thread = mAudioFlinger.checkMmapThread_l(patch->sinks[0].ext.mix.handle); 319 if (thread == 0) { 320 ALOGW("%s() bad capture I/O handle %d", 321 __func__, patch->sinks[0].ext.mix.handle); 322 status = BAD_VALUE; 323 goto exit; 324 } 325 } 326 status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 327 // remove stale audio patch with same input as sink if any 328 for (auto& iter : mPatches) { 329 if (iter.second.mAudioPatch.sinks[0].ext.mix.handle == thread->id()) { 330 mPatches.erase(iter.first); 331 break; 332 } 333 } 334 } else { 335 sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice(); 336 status = hwDevice->createAudioPatch(patch->num_sources, 337 patch->sources, 338 patch->num_sinks, 339 patch->sinks, 340 &halHandle); 341 if (status == INVALID_OPERATION) goto exit; 342 } 343 } 344 } break; 345 case AUDIO_PORT_TYPE_MIX: { 346 audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 347 ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(srcModule); 348 if (index < 0) { 349 ALOGW("%s() bad src hw module %d", __func__, srcModule); 350 status = BAD_VALUE; 351 goto exit; 352 } 353 // limit to connections between devices and output streams 354 audio_devices_t type = AUDIO_DEVICE_NONE; 355 for (unsigned int i = 0; i < patch->num_sinks; i++) { 356 if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { 357 ALOGW("%s() invalid sink type %d for mix source", 358 __func__, patch->sinks[i].type); 359 status = BAD_VALUE; 360 goto exit; 361 } 362 // limit to connections between sinks and sources on same HW module 363 if (patch->sinks[i].ext.device.hw_module != srcModule) { 364 status = BAD_VALUE; 365 goto exit; 366 } 367 type |= patch->sinks[i].ext.device.type; 368 } 369 sp<ThreadBase> thread = 370 mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 371 if (thread == 0) { 372 thread = mAudioFlinger.checkMmapThread_l(patch->sources[0].ext.mix.handle); 373 if (thread == 0) { 374 ALOGW("%s() bad playback I/O handle %d", 375 __func__, patch->sources[0].ext.mix.handle); 376 status = BAD_VALUE; 377 goto exit; 378 } 379 } 380 if (thread == mAudioFlinger.primaryPlaybackThread_l()) { 381 AudioParameter param = AudioParameter(); 382 param.addInt(String8(AudioParameter::keyRouting), (int)type); 383 384 mAudioFlinger.broacastParametersToRecordThreads_l(param.toString()); 385 } 386 387 status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 388 389 // remove stale audio patch with same output as source if any 390 for (auto& iter : mPatches) { 391 if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id()) { 392 mPatches.erase(iter.first); 393 break; 394 } 395 } 396 } break; 397 default: 398 status = BAD_VALUE; 399 goto exit; 400 } 401 exit: 402 ALOGV("%s() status %d", __func__, status); 403 if (status == NO_ERROR) { 404 *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH); 405 newPatch.mHalHandle = halHandle; 406 mPatches.insert(std::make_pair(*handle, std::move(newPatch))); 407 if (insertedModule != AUDIO_MODULE_HANDLE_NONE) { 408 addSoftwarePatchToInsertedModules(insertedModule, *handle); 409 } 410 ALOGV("%s() added new patch handle %d halHandle %d", __func__, *handle, halHandle); 411 } else { 412 newPatch.clearConnections(this); 413 } 414 return status; 415 } 416 417 AudioFlinger::PatchPanel::Patch::~Patch() 418 { 419 ALOGE_IF(isSoftware(), "Software patch connections leaked %d %d", 420 mRecord.handle(), mPlayback.handle()); 421 } 422 423 status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) 424 { 425 // create patch from source device to record thread input 426 status_t status = panel->createAudioPatch( 427 PatchBuilder().addSource(mAudioPatch.sources[0]). 428 addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(), 429 mRecord.handlePtr()); 430 if (status != NO_ERROR) { 431 *mRecord.handlePtr() = AUDIO_PATCH_HANDLE_NONE; 432 return status; 433 } 434 435 // create patch from playback thread output to sink device 436 if (mAudioPatch.num_sinks != 0) { 437 status = panel->createAudioPatch( 438 PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(), 439 mPlayback.handlePtr()); 440 if (status != NO_ERROR) { 441 *mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE; 442 return status; 443 } 444 } else { 445 *mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE; 446 } 447 448 // use a pseudo LCM between input and output framecount 449 size_t playbackFrameCount = mPlayback.thread()->frameCount(); 450 int playbackShift = __builtin_ctz(playbackFrameCount); 451 size_t recordFrameCount = mRecord.thread()->frameCount(); 452 int shift = __builtin_ctz(recordFrameCount); 453 if (playbackShift < shift) { 454 shift = playbackShift; 455 } 456 size_t frameCount = (playbackFrameCount * recordFrameCount) >> shift; 457 ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu", 458 __func__, playbackFrameCount, recordFrameCount, frameCount); 459 460 // create a special record track to capture from record thread 461 uint32_t channelCount = mPlayback.thread()->channelCount(); 462 audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 463 audio_channel_mask_t outChannelMask = mPlayback.thread()->channelMask(); 464 uint32_t sampleRate = mPlayback.thread()->sampleRate(); 465 audio_format_t format = mPlayback.thread()->format(); 466 467 audio_format_t inputFormat = mRecord.thread()->format(); 468 if (!audio_is_linear_pcm(inputFormat)) { 469 // The playbackThread format will say PCM for IEC61937 packetized stream. 470 // Use recordThread format. 471 format = inputFormat; 472 } 473 audio_input_flags_t inputFlags = mAudioPatch.sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? 474 mAudioPatch.sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; 475 if (sampleRate == mRecord.thread()->sampleRate() && 476 inChannelMask == mRecord.thread()->channelMask() && 477 mRecord.thread()->fastTrackAvailable() && 478 mRecord.thread()->hasFastCapture()) { 479 // Create a fast track if the record thread has fast capture to get better performance. 480 // Only enable fast mode when there is no resample needed. 481 inputFlags = (audio_input_flags_t) (inputFlags | AUDIO_INPUT_FLAG_FAST); 482 } else { 483 // Fast mode is not available in this case. 484 inputFlags = (audio_input_flags_t) (inputFlags & ~AUDIO_INPUT_FLAG_FAST); 485 } 486 sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord( 487 mRecord.thread().get(), 488 sampleRate, 489 inChannelMask, 490 format, 491 frameCount, 492 NULL, 493 (size_t)0 /* bufferSize */, 494 inputFlags); 495 status = mRecord.checkTrack(tempRecordTrack.get()); 496 if (status != NO_ERROR) { 497 return status; 498 } 499 500 audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? 501 mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE; 502 audio_stream_type_t streamType = AUDIO_STREAM_PATCH; 503 if (mAudioPatch.num_sources == 2 && mAudioPatch.sources[1].type == AUDIO_PORT_TYPE_MIX) { 504 // "reuse one existing output mix" case 505 streamType = mAudioPatch.sources[1].ext.mix.usecase.stream; 506 } 507 if (mPlayback.thread()->hasFastMixer()) { 508 // Create a fast track if the playback thread has fast mixer to get better performance. 509 // Note: we should have matching channel mask, sample rate, and format by the logic above. 510 outputFlags = (audio_output_flags_t) (outputFlags | AUDIO_OUTPUT_FLAG_FAST); 511 } else { 512 outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST); 513 } 514 515 // create a special playback track to render to playback thread. 516 // this track is given the same buffer as the PatchRecord buffer 517 sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack( 518 mPlayback.thread().get(), 519 streamType, 520 sampleRate, 521 outChannelMask, 522 format, 523 frameCount, 524 tempRecordTrack->buffer(), 525 tempRecordTrack->bufferSize(), 526 outputFlags); 527 status = mPlayback.checkTrack(tempPatchTrack.get()); 528 if (status != NO_ERROR) { 529 return status; 530 } 531 532 // tie playback and record tracks together 533 mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack); 534 mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack); 535 536 // start capture and playback 537 mRecord.track()->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE); 538 mPlayback.track()->start(); 539 540 return status; 541 } 542 543 void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel) 544 { 545 ALOGV("%s() mRecord.handle %d mPlayback.handle %d", 546 __func__, mRecord.handle(), mPlayback.handle()); 547 mRecord.stopTrack(); 548 mPlayback.stopTrack(); 549 mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle. 550 mRecord.closeConnections(panel); 551 mPlayback.closeConnections(panel); 552 } 553 554 status_t AudioFlinger::PatchPanel::Patch::getLatencyMs(double *latencyMs) const 555 { 556 if (!isSoftware()) return INVALID_OPERATION; 557 558 auto recordTrack = mRecord.const_track(); 559 if (recordTrack.get() == nullptr) return INVALID_OPERATION; 560 561 auto playbackTrack = mPlayback.const_track(); 562 if (playbackTrack.get() == nullptr) return INVALID_OPERATION; 563 564 // Latency information for tracks may be called without obtaining 565 // the underlying thread lock. 566 // 567 // We use record server latency + playback track latency (generally smaller than the 568 // reverse due to internal biases). 569 // 570 // TODO: is this stable enough? Consider a PatchTrack synchronized version of this. 571 572 // For PCM tracks get server latency. 573 if (audio_is_linear_pcm(recordTrack->format())) { 574 double recordServerLatencyMs, playbackTrackLatencyMs; 575 if (recordTrack->getServerLatencyMs(&recordServerLatencyMs) == OK 576 && playbackTrack->getTrackLatencyMs(&playbackTrackLatencyMs) == OK) { 577 *latencyMs = recordServerLatencyMs + playbackTrackLatencyMs; 578 return OK; 579 } 580 } 581 582 // See if kernel latencies are available. 583 // If so, do a frame diff and time difference computation to estimate 584 // the total patch latency. This requires that frame counts are reported by the 585 // HAL are matched properly in the case of record overruns and playback underruns. 586 ThreadBase::TrackBase::FrameTime recordFT{}, playFT{}; 587 recordTrack->getKernelFrameTime(&recordFT); 588 playbackTrack->getKernelFrameTime(&playFT); 589 if (recordFT.timeNs > 0 && playFT.timeNs > 0) { 590 const int64_t frameDiff = recordFT.frames - playFT.frames; 591 const int64_t timeDiffNs = recordFT.timeNs - playFT.timeNs; 592 593 // It is possible that the patch track and patch record have a large time disparity because 594 // one thread runs but another is stopped. We arbitrarily choose the maximum timestamp 595 // time difference based on how often we expect the timestamps to update in normal operation 596 // (typical should be no more than 50 ms). 597 // 598 // If the timestamps aren't sampled close enough, the patch latency is not 599 // considered valid. 600 // 601 // TODO: change this based on more experiments. 602 constexpr int64_t maxValidTimeDiffNs = 200 * NANOS_PER_MILLISECOND; 603 if (std::abs(timeDiffNs) < maxValidTimeDiffNs) { 604 *latencyMs = frameDiff * 1e3 / recordTrack->sampleRate() 605 - timeDiffNs * 1e-6; 606 return OK; 607 } 608 } 609 610 return INVALID_OPERATION; 611 } 612 613 String8 AudioFlinger::PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const 614 { 615 // TODO: Consider table dump form for patches, just like tracks. 616 String8 result = String8::format("Patch %d: thread %p => thread %p", 617 myHandle, mRecord.const_thread().get(), mPlayback.const_thread().get()); 618 619 // add latency if it exists 620 double latencyMs; 621 if (getLatencyMs(&latencyMs) == OK) { 622 result.appendFormat(" latency: %.2lf ms", latencyMs); 623 } 624 return result; 625 } 626 627 /* Disconnect a patch */ 628 status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle) 629 { 630 ALOGV("%s handle %d", __func__, handle); 631 status_t status = NO_ERROR; 632 633 auto iter = mPatches.find(handle); 634 if (iter == mPatches.end()) { 635 return BAD_VALUE; 636 } 637 Patch &removedPatch = iter->second; 638 const struct audio_patch &patch = removedPatch.mAudioPatch; 639 640 const struct audio_port_config &src = patch.sources[0]; 641 switch (src.type) { 642 case AUDIO_PORT_TYPE_DEVICE: { 643 sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module); 644 if (hwDevice == 0) { 645 ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module); 646 status = BAD_VALUE; 647 break; 648 } 649 650 if (removedPatch.isSoftware()) { 651 removedPatch.clearConnections(this); 652 break; 653 } 654 655 if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) { 656 audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle; 657 sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l(ioHandle); 658 if (thread == 0) { 659 thread = mAudioFlinger.checkMmapThread_l(ioHandle); 660 if (thread == 0) { 661 ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle); 662 status = BAD_VALUE; 663 break; 664 } 665 } 666 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle); 667 } else { 668 status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle); 669 } 670 } break; 671 case AUDIO_PORT_TYPE_MIX: { 672 if (findHwDeviceByModule(src.ext.mix.hw_module) == 0) { 673 ALOGW("%s() bad src hw module %d", __func__, src.ext.mix.hw_module); 674 status = BAD_VALUE; 675 break; 676 } 677 audio_io_handle_t ioHandle = src.ext.mix.handle; 678 sp<ThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle); 679 if (thread == 0) { 680 thread = mAudioFlinger.checkMmapThread_l(ioHandle); 681 if (thread == 0) { 682 ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle); 683 status = BAD_VALUE; 684 break; 685 } 686 } 687 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle); 688 } break; 689 default: 690 status = BAD_VALUE; 691 } 692 693 mPatches.erase(iter); 694 removeSoftwarePatchFromInsertedModules(handle); 695 return status; 696 } 697 698 /* List connected audio ports and they attributes */ 699 status_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused, 700 struct audio_patch *patches __unused) 701 { 702 ALOGV(__func__); 703 return NO_ERROR; 704 } 705 706 status_t AudioFlinger::PatchPanel::getDownstreamSoftwarePatches( 707 audio_io_handle_t stream, 708 std::vector<AudioFlinger::PatchPanel::SoftwarePatch> *patches) const 709 { 710 for (const auto& module : mInsertedModules) { 711 if (module.second.streams.count(stream)) { 712 for (const auto& patchHandle : module.second.sw_patches) { 713 const auto& patch_iter = mPatches.find(patchHandle); 714 if (patch_iter != mPatches.end()) { 715 const Patch &patch = patch_iter->second; 716 patches->emplace_back(*this, patchHandle, 717 patch.mPlayback.const_thread()->id(), 718 patch.mRecord.const_thread()->id()); 719 } else { 720 ALOGE("Stale patch handle in the cache: %d", patchHandle); 721 } 722 } 723 return OK; 724 } 725 } 726 // The stream is not associated with any of inserted modules. 727 return BAD_VALUE; 728 } 729 730 void AudioFlinger::PatchPanel::notifyStreamOpened( 731 AudioHwDevice *audioHwDevice, audio_io_handle_t stream) 732 { 733 if (audioHwDevice->isInsert()) { 734 mInsertedModules[audioHwDevice->handle()].streams.insert(stream); 735 } 736 } 737 738 void AudioFlinger::PatchPanel::notifyStreamClosed(audio_io_handle_t stream) 739 { 740 for (auto& module : mInsertedModules) { 741 module.second.streams.erase(stream); 742 } 743 } 744 745 AudioHwDevice* AudioFlinger::PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module) 746 { 747 if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr; 748 ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module); 749 if (index < 0) { 750 ALOGW("%s() bad hw module %d", __func__, module); 751 return nullptr; 752 } 753 return mAudioFlinger.mAudioHwDevs.valueAt(index); 754 } 755 756 sp<DeviceHalInterface> AudioFlinger::PatchPanel::findHwDeviceByModule(audio_module_handle_t module) 757 { 758 AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module); 759 return audioHwDevice ? audioHwDevice->hwDevice() : nullptr; 760 } 761 762 void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules( 763 audio_module_handle_t module, audio_patch_handle_t handle) 764 { 765 mInsertedModules[module].sw_patches.insert(handle); 766 } 767 768 void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules( 769 audio_patch_handle_t handle) 770 { 771 for (auto& module : mInsertedModules) { 772 module.second.sw_patches.erase(handle); 773 } 774 } 775 776 void AudioFlinger::PatchPanel::dump(int fd) const 777 { 778 String8 patchPanelDump; 779 const char *indent = " "; 780 781 // Only dump software patches. 782 bool headerPrinted = false; 783 for (const auto& iter : mPatches) { 784 if (iter.second.isSoftware()) { 785 if (!headerPrinted) { 786 patchPanelDump += "\nSoftware patches:\n"; 787 headerPrinted = true; 788 } 789 patchPanelDump.appendFormat("%s%s\n", indent, iter.second.dump(iter.first).string()); 790 } 791 } 792 793 headerPrinted = false; 794 for (const auto& module : mInsertedModules) { 795 if (!module.second.streams.empty() || !module.second.sw_patches.empty()) { 796 if (!headerPrinted) { 797 patchPanelDump += "\nTracked inserted modules:\n"; 798 headerPrinted = true; 799 } 800 String8 moduleDump = String8::format("Module %d: I/O handles: ", module.first); 801 for (const auto& stream : module.second.streams) { 802 moduleDump.appendFormat("%d ", stream); 803 } 804 moduleDump.append("; SW Patches: "); 805 for (const auto& patch : module.second.sw_patches) { 806 moduleDump.appendFormat("%d ", patch); 807 } 808 patchPanelDump.appendFormat("%s%s\n", indent, moduleDump.string()); 809 } 810 } 811 812 if (!patchPanelDump.isEmpty()) { 813 write(fd, patchPanelDump.string(), patchPanelDump.size()); 814 } 815 } 816 817 } // namespace android 818