String8 A2dpAudioInterface::getParameters(const String8& keys) { AudioParameter param = AudioParameter(keys); AudioParameter a2dpParam = AudioParameter(); String8 value; String8 key; key = "bluetooth_enabled"; if (param.get(key, value) == NO_ERROR) { value = mBluetoothEnabled ? "true" : "false"; a2dpParam.add(key, value); param.remove(key); } key = "A2dpSuspended"; if (param.get(key, value) == NO_ERROR) { value = mSuspended ? "true" : "false"; a2dpParam.add(key, value); param.remove(key); } String8 keyValuePairs = a2dpParam.toString(); if (param.size()) { if (keyValuePairs != "") { keyValuePairs += ";"; } keyValuePairs += mHardwareInterface->getParameters(param.toString()); } LOGV("getParameters() %s", keyValuePairs.string()); return keyValuePairs; }
status_t AudioStreamInWrapper::setParameters(const String8& keyValuePairs) { LOGV("AudioStreamInWrapper::setParameters(\"%s\")", keyValuePairs.string()); AudioParameter param = AudioParameter(keyValuePairs); String8 key; status_t status = NO_ERROR; int device; // reading routing parameter key = String8(AudioParameter::keyRouting); if (param.getInt(key, device) == NO_ERROR) { LOGV("set input routing %x", device); if (device & (device - 1)) { status = BAD_VALUE; } else { mDevices = device; status = mHardware->doRouting(); } param.remove(key); } if (param.size()) { status = BAD_VALUE; } return status; }
status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); String8 value; String8 key; status_t status = NO_ERROR; LOGV("setParameters() %s", keyValuePairs.string()); key = "bluetooth_enabled"; if (param.get(key, value) == NO_ERROR) { mBluetoothEnabled = (value == "true"); if (mOutput) { mOutput->setBluetoothEnabled(mBluetoothEnabled); } param.remove(key); } key = String8("A2dpSuspended"); if (param.get(key, value) == NO_ERROR) { mSuspended = (value == "true"); if (mOutput) { mOutput->setSuspended(mSuspended); } param.remove(key); } if (param.size()) { status_t hwStatus = mHardwareInterface->setParameters(param.toString()); if (status == NO_ERROR) { status = hwStatus; } } return status; }
status_t AudioStreamInMotorola::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); status_t status = NO_ERROR; int device; String8 key; int source; LOGD("setParameters(%s) called", keyValuePairs.string()); // reading routing parameter key = String8(AudioParameter::keyRouting); if (param.getInt(key, device) == NO_ERROR) { LOGD("setParameters(): set input routing %x", device); if (device & (device - 1)) { LOGE("setParameters(): device value is invalid for routing"); status = BAD_VALUE; } else { mDevices = device; status = mHardware->doRouting(); } param.remove(key); } if (param.size()) { LOGE("setParameters(): parameter size is invalid"); status = BAD_VALUE; } return status; }
status_t AudioAACStreamIn::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); String8 key = String8(AudioParameter::keyRouting); status_t status = NO_ERROR; int device; ALOGV("setParameters() %s", keyValuePairs.string()); if (param.getInt(key, device) == NO_ERROR) { mDevice = device; param.remove(key); } if (param.size()) { status = BAD_VALUE; } return status; }
status_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); String8 key = String8(AudioParameter::keyRouting); status_t status = NO_ERROR; int device; LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string()); if (param.getInt(key, device) == NO_ERROR) { mDevices = device; LOGV("set output routing %x", mDevices); status = mHardware->doRouting(); param.remove(key); } if (param.size()) { status = BAD_VALUE; } return status; }
status_t AudioStreamOutWrapper::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); String8 key = String8(AudioParameter::keyRouting); status_t status = NO_ERROR; int device; LOGV("AudioStreamOutWrapper::setParameters(\"%s\")", keyValuePairs.string()); if (param.getInt(key, device) == NO_ERROR) { mDevices = device; LOGV("set output routing %x", mDevices); uint32_t routes = devicesToRoutes(mDevices); status = mHardware->setRouting(AudioSystem::MODE_NORMAL, routes); param.remove(key); } if (param.size()) { status = BAD_VALUE; } return status; }
status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs) { AudioParameter param = AudioParameter(keyValuePairs); String8 value; String8 key = String8("a2dp_sink_address"); status_t status = NO_ERROR; int device; LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string()); if (param.get(key, value) == NO_ERROR) { if (value.length() != strlen("00:00:00:00:00:00")) { status = BAD_VALUE; } else { setAddress(value.string()); } param.remove(key); } key = String8("closing"); if (param.get(key, value) == NO_ERROR) { mClosing = (value == "true"); param.remove(key); } key = AudioParameter::keyRouting; if (param.getInt(key, device) == NO_ERROR) { if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) { mDevice = device; status = NO_ERROR; } else { status = BAD_VALUE; } param.remove(key); } if (param.size()) { status = BAD_VALUE; } return status; }
status_t AudioHardwareOutput::setParameters(const char* kvpairs) { AudioParameter param = AudioParameter(String8(kvpairs)); status_t status = NO_ERROR; float floatVal; int intVal; Settings initial, s; { // Record the initial state of the settings from inside the lock. Then // leave the lock in order to parse the changes to be made. Mutex::Autolock _l(mSettingsLock); initial = s = mSettings; } /*************************************************************** * HDMI Audio Options * ***************************************************************/ if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) { s.hdmi.allowed = (intVal != 0); param.remove(kHDMIAllowedParamKey); } if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) && (floatVal >= 0.0) && (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0); s.hdmi.delayCompUsec = delay_comp; param.remove(kHDMIDelayCompParamKey); } if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) { s.hdmi.isFixed = (intVal != 0); param.remove(kFixedHDMIOutputParamKey); } if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR) && (floatVal <= 0.0)) { s.hdmi.fixedLvl = floatVal; param.remove(kFixedHDMIOutputLevelParamKey); } /*************************************************************** * Other Options * ***************************************************************/ if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) && (floatVal >= 0.0) && (floatVal <= AudioOutput::kMaxDelayCompensationMSec)) { s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0); param.remove(kVideoDelayCompParamKey); } if (param.size()) status = BAD_VALUE; // If there was a change made to settings, go ahead and apply it now. bool allowedOutputsChanged = false; if (memcmp(&initial, &s, sizeof(initial))) { Mutex::Autolock _l1(mOutputLock); Mutex::Autolock _l2(mSettingsLock); if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi))) allowedOutputsChanged = allowedOutputsChanged || applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi, HDMIAudioOutput::classDevMask()); if (initial.videoDelayCompUsec != s.videoDelayCompUsec) mSettings.videoDelayCompUsec = s.videoDelayCompUsec; uint32_t tmp = 0; if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec)) tmp = mSettings.hdmi.delayCompUsec; if (mMaxDelayCompUsec != tmp) mMaxDelayCompUsec = tmp; } if (allowedOutputsChanged) { Mutex::Autolock _l(mStreamLock); updateTgtDevices_l(); } return status; }
status_t AudioALSAStreamOut::setParameters(const String8 &keyValuePairs) { ALOGD("+%s(): %s", __FUNCTION__, keyValuePairs.string()); AudioParameter param = AudioParameter(keyValuePairs); /// keys const String8 keyRouting = String8(AudioParameter::keyRouting); const String8 keySampleRate = String8(AudioParameter::keySamplingRate); const String8 keyDynamicSampleRate = String8("DynamicSampleRate"); const String8 keyLowLatencyMode = String8("LowLatencyMode"); const String8 keyRoutingToNone = String8(AudioParameter::keyRoutingToNone); const String8 keyFmDirectControl = String8(AudioParameter::keyFmDirectControl); audio_devices_t mydevice = 0; /// parse key value pairs status_t status = NO_ERROR; int value = 0; /// routing if (param.getInt(keyRouting, value) == NO_ERROR) { param.remove(keyRouting); mydevice = static_cast<audio_devices_t>(value); ALOGD("%s(), mydevice 0x%x", __FUNCTION__, mydevice); AudioAutoTimeoutLock _l(mLock); if (mStreamOutType == STREAM_OUT_PRIMARY) { status = mStreamManager->routingOutputDevice(mStreamAttributeSource.output_devices, static_cast<audio_devices_t>(value)); } else if ((mStreamOutType == STREAM_OUT_HDMI_STEREO) || (mStreamOutType == STREAM_OUT_HDMI_MULTI_CHANNEL)) { ALOGD("%s(), HDMI \"%s\"", __FUNCTION__, param.toString().string()); status = mStreamManager->routingOutputDevice(mStreamAttributeSource.output_devices, static_cast<audio_devices_t>(value)); } else { ALOGW("%s(), NUM_STREAM_OUT_TYPE \"%s\"", __FUNCTION__, param.toString().string()); status = INVALID_OPERATION; } } if (param.getInt(keyFmDirectControl, value) == NO_ERROR) { param.remove(keyFmDirectControl); AudioAutoTimeoutLock _l(mLock); AudioALSAFMController::getInstance()->setUseFmDirectConnectionMode(value?true:false); } // routing none, for no stream but has device change. e.g. vow path change if (param.getInt(keyRoutingToNone, value) == NO_ERROR) { param.remove(keyRoutingToNone); AudioAutoTimeoutLock _l(mLock); status = mStreamManager->DeviceNoneUpdate(); } // samplerate if (param.getInt(keySampleRate, value) == NO_ERROR) { param.remove(keySampleRate); AudioAutoTimeoutLock _l(mLock); if (mPlaybackHandler == NULL) { UpdateSampleRate(value); } else { status = INVALID_OPERATION; } } /// sample rate if (param.getInt(keyDynamicSampleRate, value) == NO_ERROR) { param.remove(keyRouting); AudioAutoTimeoutLock _l(mLock); if (mStreamOutType == STREAM_OUT_PRIMARY) { status = NO_ERROR; //AudioALSASampleRateController::getInstance()->setPrimaryStreamOutSampleRate(value); // TODO(Harvey): enable it later } else { ALOGW("%s(), HDMI bypass \"%s\"", __FUNCTION__, param.toString().string()); status = INVALID_OPERATION; } } #ifdef MTK_DYNAMIC_CHANGE_HAL_BUFFER_SIZE // set low latency if (param.getInt(keyLowLatencyMode, value) == NO_ERROR) { param.remove(keyLowLatencyMode); setLowLatencyMode(value); } #endif if (param.size()) { ALOGW("%s(), still have param.size() = %d, remain param = \"%s\"", __FUNCTION__, param.size(), param.toString().string()); status = BAD_VALUE; } ALOGD("-%s(): %s ", __FUNCTION__, keyValuePairs.string()); return status; }
status_t AudioALSAStreamIn::setParameters(const String8 &keyValuePairs) { ALOGD("+%s(): %s", __FUNCTION__, keyValuePairs.string()); AudioParameter param = AudioParameter(keyValuePairs); /// keys const String8 keyInputSource = String8(AudioParameter::keyInputSource); const String8 keyRouting = String8(AudioParameter::keyRouting); /// parse key value pairs status_t status = NO_ERROR; int value = 0; /// intput source if (param.getInt(keyInputSource, value) == NO_ERROR) { param.remove(keyInputSource); // TODO(Harvey): input source AudioAutoTimeoutLock _l(mLock); ALOGD("%s() InputSource = %d", __FUNCTION__, value); mStreamAttributeTarget.input_source = static_cast<audio_source_t>(value); if (mStreamAttributeTarget.BesRecord_Info.besrecord_ForceMagiASREnable == true) { ALOGD("%s() force input source to AUDIO_SOURCE_CUSTOMIZATION1", __FUNCTION__); mStreamAttributeTarget.input_source = AUDIO_SOURCE_CUSTOMIZATION1; } if (mStreamAttributeTarget.BesRecord_Info.besrecord_ForceAECRecEnable == true) { ALOGD("%s() force input source to AUDIO_SOURCE_CUSTOMIZATION2", __FUNCTION__); mStreamAttributeTarget.input_source = AUDIO_SOURCE_CUSTOMIZATION2; } } /// routing if (param.getInt(keyRouting, value) == NO_ERROR) { param.remove(keyRouting); AudioAutoTimeoutLock _l(mLock); audio_devices_t inputdevice = static_cast<audio_devices_t>(value); //only need to modify the device while VoIP if (mStreamAttributeTarget.BesRecord_Info.besrecord_voip_enable == true) { if (mStreamAttributeTarget.output_devices == AUDIO_DEVICE_OUT_SPEAKER) { if (inputdevice == AUDIO_DEVICE_IN_BUILTIN_MIC) { if (USE_REFMIC_IN_LOUDSPK == 1) { inputdevice = AUDIO_DEVICE_IN_BACK_MIC; ALOGD("%s() force change to back mic", __FUNCTION__); } } } } status = mStreamManager->routingInputDevice(mStreamAttributeTarget.input_device, inputdevice); } if (param.size()) { ALOGW("%s(), still have param.size() = %d, remain param = \"%s\"", __FUNCTION__, param.size(), param.toString().string()); status = BAD_VALUE; } ALOGD("-%s(): %s ", __FUNCTION__, keyValuePairs.string()); return status; }
// insertCommand_l() must be called with mLock held void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs) { ssize_t i; Vector <AudioCommand *> removedCommands; command->mTime = systemTime() + milliseconds(delayMs); // acquire wake lock to make sure delayed commands are processed if (mName != "" && mAudioCommands.isEmpty()) { acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string()); } // check same pending commands with later time stamps and eliminate them for (i = mAudioCommands.size()-1; i >= 0; i--) { AudioCommand *command2 = mAudioCommands[i]; // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands if (command2->mTime <= command->mTime) break; if (command2->mCommand != command->mCommand) continue; switch (command->mCommand) { case SET_PARAMETERS: { ParametersData *data = (ParametersData *)command->mParam; ParametersData *data2 = (ParametersData *)command2->mParam; if (data->mIO != data2->mIO) break; LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string()); AudioParameter param = AudioParameter(data->mKeyValuePairs); AudioParameter param2 = AudioParameter(data2->mKeyValuePairs); for (size_t j = 0; j < param.size(); j++) { String8 key; String8 value; param.getAt(j, key, value); for (size_t k = 0; k < param2.size(); k++) { String8 key2; String8 value2; param2.getAt(k, key2, value2); if (key2 == key) { param2.remove(key2); LOGV("Filtering out parameter %s", key2.string()); break; } } } // if all keys have been filtered out, remove the command. // otherwise, update the key value pairs if (param2.size() == 0) { removedCommands.add(command2); } else { data2->mKeyValuePairs = param2.toString(); } } break; case SET_VOLUME: { VolumeData *data = (VolumeData *)command->mParam; VolumeData *data2 = (VolumeData *)command2->mParam; if (data->mIO != data2->mIO) break; if (data->mStream != data2->mStream) break; LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream); removedCommands.add(command2); } break; #ifdef HAVE_FM_RADIO case SET_FM_VOLUME: { removedCommands.add(command2); } break; #endif case START_TONE: case STOP_TONE: default: break; } } // remove filtered commands for (size_t j = 0; j < removedCommands.size(); j++) { // removed commands always have time stamps greater than current command for (size_t k = i + 1; k < mAudioCommands.size(); k++) { if (mAudioCommands[k] == removedCommands[j]) { LOGV("suppressing command: %d", mAudioCommands[k]->mCommand); mAudioCommands.removeAt(k); break; } } } removedCommands.clear(); // insert command at the right place according to its time stamp LOGV("inserting command: %d at index %d, num commands %d", command->mCommand, (int)i+1, mAudioCommands.size()); mAudioCommands.insertAt(command, i + 1); }