String8 AudioALSAStreamOut::getParameters(const String8 &keys) { #ifdef MTK_DYNAMIC_CHANGE_HAL_BUFFER_SIZE ALOGD("%s, keyvalue %s", __FUNCTION__, keys.string()); String8 value; String8 keyLowLatency = String8("LowLatency"); AudioParameter param = AudioParameter(keys); AudioParameter returnParam = AudioParameter(); if (param.get(keyLowLatency, value) == NO_ERROR) { param.remove(keyLowLatency); char buf[10]; sprintf(buf, "%d", LOW_LATENCY_HAL_BUFFER_SIZE); returnParam.add(keyLowLatency, String8(buf)); } const String8 keyValuePairs = returnParam.toString(); ALOGD("-%s(), return \"%s\"", __FUNCTION__, keyValuePairs.string()); return keyValuePairs; #else ALOGD("%s()", __FUNCTION__); AudioParameter param = AudioParameter(keys); return param.toString(); #endif }
status_t AudioPolicyManager::startInput(audio_io_handle_t input) { status_t status = AudioPolicyManagerBase::startInput(input); if (status == NO_ERROR) { AudioInputDescriptor *inputDesc = mInputs.valueFor(input); String8 key = String8("Input Source"); String8 value; switch(inputDesc->mInputSource) { case AUDIO_SOURCE_VOICE_RECOGNITION: value = String8("Voice Recognition"); break; case AUDIO_SOURCE_CAMCORDER: value = String8("Camcorder"); break; case AUDIO_SOURCE_DEFAULT: case AUDIO_SOURCE_MIC: value = String8("Default"); default: break; } AudioParameter param = AudioParameter(); param.add(key, value); mpClientInterface->setParameters(input, param.toString()); } return status; }
void AudioPolicyManagerSPRD::releaseOutput(audio_io_handle_t output) { #ifdef DUMP_DEBUG ALOGD("releaseOutput() %d", output); #endif ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { ALOGW("releaseOutput() releasing unknown output %d", output); return; } if(is_voip_set) { AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); if(outputDesc->mRefCount[AudioSystem::VOICE_CALL] == 0) { AudioParameter param; param.add(String8("sprd_voip_start"), String8("false")); mpClientInterface->setParameters(0, param.toString()); is_voip_set = false; } } #ifdef AUDIO_POLICY_TEST int testIndex = testOutputIndex(output); if (testIndex != 0) { AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); if (outputDesc->isActive()) { mpClientInterface->closeOutput(output); delete mOutputs.valueAt(index); mOutputs.removeItem(output); mTestOutputs[testIndex] = 0; } return; } #endif //AUDIO_POLICY_TEST AudioOutputDescriptor *desc = mOutputs.valueAt(index); if (desc->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) { if (desc->mDirectOpenCount <= 0) { ALOGW("releaseOutput() invalid open count %d for output %d", desc->mDirectOpenCount, output); return; } if (--desc->mDirectOpenCount == 0) { closeOutput(output); // If effects where present on the output, audioflinger moved them to the primary // output by default: move them back to the appropriate output. audio_io_handle_t dstOutput = getOutputForEffect(); if (dstOutput != mPrimaryOutput) { mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mPrimaryOutput, dstOutput); } } } }
String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys) { AudioParameter param = AudioParameter(keys); String8 value; String8 key = String8("a2dp_sink_address"); if (param.get(key, value) == NO_ERROR) { value = mA2dpAddress; param.add(key, value); } key = AudioParameter::keyRouting; if (param.get(key, value) == NO_ERROR) { param.addInt(key, (int)mDevice); } LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string()); return param.toString(); }
status_t AudioPolicyManagerSPRD::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { #ifdef DUMP_DEBUG ALOGD("startOutput() output %d, stream %d, session %d", output, stream, session); #endif ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { ALOGW("startOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); // increment usage count for this stream on the requested output: // NOTE that the usage count is the same for duplicated output and hardware output which is // necessary for a correct control of hardware output routing by startOutput() and stopOutput() outputDesc->changeRefCount(stream, 1); #ifdef DUMP_DEBUG ALOGD("startOutput() is_voip_set %d,stream %d,",is_voip_set,stream); #endif if((!is_voip_set)&&(stream == AudioSystem::VOICE_CALL)) { for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i); #ifdef DUMP_DEBUG ALOGD("startOutput() outputDesc->mRefCount[AudioSystem::VOICE_CALL] %d",outputDesc->mRefCount[AudioSystem::VOICE_CALL]); #endif if(outputDesc->mRefCount[AudioSystem::VOICE_CALL] == 1) { AudioParameter param; param.add(String8("sprd_voip_start"), String8("true")); mpClientInterface->setParameters(0, param.toString()); is_voip_set = true; } } } if (outputDesc->mRefCount[stream] == 1) { audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/); routing_strategy strategy = getStrategy(stream); bool shouldWait = (strategy == STRATEGY_SONIFICATION) || (strategy == STRATEGY_SONIFICATION_RESPECTFUL); uint32_t waitMs = 0; bool force = false; for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueAt(i); if (desc != outputDesc) { // force a device change if any other output is managed by the same hw // module and has a current device selection that differs from selected device. // In this case, the audio HAL must receive the new device selection so that it can // change the device currently selected by the other active output. if (outputDesc->sharesHwModuleWith(desc) && desc->device() != newDevice) { force = true; } // wait for audio on other active outputs to be presented when starting // a notification so that audio focus effect can propagate. uint32_t latency = desc->latency(); if (shouldWait && desc->isActive(latency * 2) && (waitMs < latency)) { waitMs = latency; } } } uint32_t muteWaitMs = setOutputDevice(output, newDevice, force); // handle special case for sonification while in call if (isInCall()) { handleIncallSonification(stream, true, false); } // apply volume rules for current stream and device if necessary // filter devices according to output selected if(!outputDesc->isDuplicated()) newDevice = (audio_devices_t)(newDevice & outputDesc->mProfile->mSupportedDevices); ALOGW("startOutput() select newDevice %d", newDevice); checkAndSetVolume(stream, mStreams[stream].getVolumeIndex(newDevice), output, newDevice); // update the outputs if starting an output with a stream that can affect notification // routing handleNotificationRoutingForStream(stream); if (waitMs > muteWaitMs) { usleep((waitMs - muteWaitMs) * 2 * 1000); } } return NO_ERROR; }
status_t AudioPolicyManagerSPRD::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream, int session) { #ifdef DUMP_DEBUG ALOGD("stopOutput() output %d, stream %d, session %d", output, stream, session); #endif ssize_t index = mOutputs.indexOfKey(output); if (index < 0) { ALOGW("stopOutput() unknow output %d", output); return BAD_VALUE; } AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); // handle special case for sonification while in call if (isInCall()) { handleIncallSonification(stream, false, false); } #ifdef DUMP_DEBUG ALOGD("stopOutput() is_voip_set %d,stream %d,output size %d",is_voip_set,stream,mOutputs.size()); #endif if(is_voip_set &&(stream == AudioSystem::VOICE_CALL)) { for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *outputDesc = mOutputs.valueAt(i); #ifdef DUMP_DEBUG ALOGD("stopOutput() outputDesc->mRefCount[AudioSystem::VOICE_CALL] %d",outputDesc->mRefCount[AudioSystem::VOICE_CALL]); #endif if(outputDesc->mRefCount[AudioSystem::VOICE_CALL] == 1) { AudioParameter param; param.add(String8("sprd_voip_start"), String8("false")); mpClientInterface->setParameters(0, param.toString()); is_voip_set = false; } } } if (outputDesc->mRefCount[stream] > 0) { // decrement usage count of this stream on the output outputDesc->changeRefCount(stream, -1); // store time at which the stream was stopped - see isStreamActive() if (outputDesc->mRefCount[stream] == 0) { outputDesc->mStopTime[stream] = systemTime(); audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/); // delay the device switch by twice the latency because stopOutput() is executed when // the track stop() command is received and at that time the audio track buffer can // still contain data that needs to be drained. The latency only covers the audio HAL // and kernel buffers. Also the latency does not always include additional delay in the // audio path (audio DSP, CODEC ...) setOutputDevice(output, newDevice, false, outputDesc->mLatency*2); // force restoring the device selection on other active outputs if it differs from the // one being selected for this output for (size_t i = 0; i < mOutputs.size(); i++) { audio_io_handle_t curOutput = mOutputs.keyAt(i); AudioOutputDescriptor *desc = mOutputs.valueAt(i); if (curOutput != output && desc->isActive() && outputDesc->sharesHwModuleWith(desc) && (newDevice != desc->device())) { setOutputDevice(curOutput, getNewDevice(curOutput, false /*fromCache*/), true, outputDesc->mLatency*2); } } // update the outputs if stopping one with a stream that can affect notification routing handleNotificationRoutingForStream(stream); } return NO_ERROR; } else { ALOGW("stopOutput() refcount is already 0 for output %d", output); return INVALID_OPERATION; } }