AudioTrack::AudioTrack(
)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
sharedBuffer, false /*threadCanCallJava*/, sessionId);
status_t AudioTrack::set()
{
// create the IAudioTrack
status_t status = createTrack_l(streamType,
sampleRate,
format,
(uint32_t)channelMask,
frameCount,
flags,
sharedBuffer,
output);
}
void AudioTrack::start()
{
status = mAudioTrack->start();
}
status_t AudioTrack::createTrack_l(
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
streamType,
sampleRate,
format,
channelMask,
frameCount,
trackFlags,
sharedBuffer,
output,
tid,
&mSessionId,
&status);
mAudioTrack = track;
}
sp<IAudioTrack> AudioFlinger::createTrack()
{
track = thread->createTrack_l(client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus);
trackHandle = new TrackHandle(track);
return trackHandle;
}
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l()
{
track = new Track(this, client, streamType, sampleRate, format,
channelMask, frameCount, sharedBuffer, sessionId, flags);
return track;
}
status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event,
int triggerSession){
status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
}
status_t AudioSystem::startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->startOutput(output, stream, session);
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session)
{
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
ALOGV("startOutput() tid %d", gettid());
Mutex::Autolock _l(mLock);
return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
}
static int create_legacy_ap(const struct audio_policy_device *device,
struct audio_policy_service_ops *aps_ops,
void *service,
struct audio_policy **ap)
{
lap->policy.start_output = ap_start_output;
}
static int ap_start_output(struct audio_policy *pol, audio_io_handle_t output,
audio_stream_type_t stream, int session)
{
struct legacy_audio_policy *lap = to_lap(pol);
return lap->apm->startOutput(output, (AudioSystem::stream_type)stream,
session);
}
status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
AudioSystem::stream_type stream,
int session)
{
audio_devices_t prevDevice = outputDesc->device();
audio_devices_t newDevice = getNewDevice(output, false /*fromCache*/);
routing_strategy strategy = getStrategy(stream);
uint32_t muteWaitMs = setOutputDevice(output, newDevice, force);
// apply volume rules for current stream and device if necessary
checkAndSetVolume(stream,
mStreams[stream].getVolumeIndex((audio_devices_t)newDevice),
output,
newDevice);
}
audio_devices_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
{
audio_devices_t device = (audio_devices_t)0;
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
// check the following by order of priority to request a routing change if necessary:
// 1: the strategy enforced audible is active on the output:
// use device for strategy enforced audible
// 2: we are in call or the strategy phone is active on the output:
// use device for strategy phone
// 3: the strategy sonification is active on the output:
// use device for strategy sonification
// 4: the strategy "respectful" sonification is active on the output:
// use device for strategy "respectful" sonification
// 5: the strategy media is active on the output:
// use device for strategy media
// 6: the strategy DTMF is active on the output:
// use device for strategy DTMF
if (outputDesc->isUsedByStrategy(STRATEGY_ENFORCED_AUDIBLE)) {
device = getDeviceForStrategy(STRATEGY_ENFORCED_AUDIBLE, fromCache);
} else if (isInCall() ||
outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION_RESPECTFUL)) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION_RESPECTFUL, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
} else if (outputDesc->isUsedByStrategy(STRATEGY_FM)) {
device = getDeviceForStrategy(STRATEGY_FM, fromCache);
}
ALOGV("getNewDevice() selected device %x", device);
return device;
}
audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
bool fromCache)
{
uint32_t device = 0;
if (fromCache) {
ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
strategy, mDeviceForStrategy[strategy]);
return mDeviceForStrategy[strategy];
}
switch (strategy) {
case STRATEGY_SONIFICATION_RESPECTFUL:
if (isInCall()) {
device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
} else if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
// while media is playing (or has recently played), use the same device
device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
} else {
// when media is not playing anymore, fall back on the sonification behavior
device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
}
break;
case STRATEGY_DTMF:
if (!isInCall()) {
// when off call, DTMF strategy follows the same rules as MEDIA strategy
device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
break;
}
// when in call, DTMF and PHONE strategies follow the same rules
// FALL THROUGH
case STRATEGY_PHONE:
// for phone strategy, we first consider the forced use and then the available devices by order
// of priority
switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
case AudioSystem::FORCE_BT_SCO:
if (!isInCall() || strategy != STRATEGY_DTMF) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
if (device) break;
// if SCO device is requested but no SCO device is available, fall back to default case
// FALL THROUGH
default: // FORCE_NONE
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
if (mHasA2dp && !isInCall() &&
(mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
if (device) break;
}
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
if (device) break;
device = mDefaultOutputDevice;
if (device == 0) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE");
}
break;
case AudioSystem::FORCE_SPEAKER:
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
// A2DP speaker when forcing to speaker output
if (mHasA2dp && !isInCall() &&
(mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
if (device) break;
}
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
if (device) break;
device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
if (device) break;
device = mDefaultOutputDevice;
if (device == 0) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER");
}
break;
}
break;
case STRATEGY_SONIFICATION:
// If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
// handleIncallSonification().
if (isInCall()) {
device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/);
break;
}
// FALL THROUGH
case STRATEGY_ENFORCED_AUDIBLE:
//Fix bug 137934. Note we can delete routing policy in STRATEGY_SONIFICATION
if (isInCall()) {
device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/);
break;
}
// strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION
// except in countries where not enforced in which case it follows STRATEGY_MEDIA
if (strategy == STRATEGY_SONIFICATION ||
!mStreams[AUDIO_STREAM_ENFORCED_AUDIBLE].mCanBeMuted) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
if (device == 0) {
ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION");
}
}
// The second device used for sonification is the same as the device used by media strategy
// FALL THROUGH
case STRATEGY_MEDIA: {
uint32_t device2 = 0;
switch (mForceUse[AudioSystem::FOR_MEDIA]) {
case AudioSystem::FORCE_SPEAKER:
ALOGD("geting device of force_speaker");
if (device2 == 0) {
//HTC_AUD_START, eleven add for tfa9887 fm
#if defined(BOARD_HAVE_TFA9887)
if(FM_status == 1)
device = AudioSystem::DEVICE_OUT_FM_SPEAKER;
else
#endif
//HTC_AUD_END.
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
}
break;
default:
if ((device2 == 0) && mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) &&
(getA2dpOutput() != 0) && !mA2dpSuspended) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
}
#ifdef ENABLE_HTC_SUBWOOFER
if (device2 != 0) {
char subwoofer[PROPERTY_VALUE_MAX];
property_get("htc.audio.subwoofer",subwoofer, "0");
if (atoi(subwoofer) == 1) {
device2 |= mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER;
}
}
#endif
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
}
// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
// STRATEGY_ENFORCED_AUDIBLE, 0 otherwise
device |= device2;
if (device) break;
device = mDefaultOutputDevice;
if (device == 0) {
ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA");
}
}
}break;
case STRATEGY_FM: {
//HTC_AUD_START, eleven add for FM forse use.
switch (mForceUse[AudioSystem::FOR_MEDIA]) {
case AudioSystem::FORCE_SPEAKER:
ALOGD("geting device of force_speaker");
device = AudioSystem::DEVICE_OUT_FM_SPEAKER;
break;
case AudioSystem::FORCE_NO_BT_A2DP:
ALOGD("geting device of force_headset");
device = AudioSystem::DEVICE_OUT_FM_HEADSET;
break;
case AudioSystem::FORCE_NONE:
default:
ALOGD("Do nothing for force none");
break;
}
if (device == 0) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM_HEADSET;
}
if (device == 0) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_FM_SPEAKER;
}
} break;
//HTC_AUD_END.
default:
ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
break;
}
ALOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
return (audio_devices_t)device;
}
uint32_t AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output,
audio_devices_t device,
bool force,
int delayMs)
{
// do the routing
param.addInt(String8(AudioParameter::keyRouting), (int)device);
mpClientInterface->setParameters(output, param.toString(), delayMs);
// update stream volumes according to new device
applyStreamVolumes(output, device, delayMs);
}
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
:
#ifdef AUDIO_POLICY_TEST
Thread(false),
#endif //AUDIO_POLICY_TEST
mPrimaryOutput((audio_io_handle_t)0),
mAvailableOutputDevices((audio_devices_t)0),
mPhoneState(AudioSystem::MODE_NORMAL),
mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0),
mA2dpSuspended(false), mHasA2dp(false), mHasUsb(false), mHasStartupSound(true)
{
mpClientInterface = clientInterface;
}
static int create_legacy_ap(const struct audio_policy_device *device,
struct audio_policy_service_ops *aps_ops,
void *service,
struct audio_policy **ap)
{
lap->apm = createAudioPolicyManager(lap->service_client);
}
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
return new AudioPolicyManagerSPRD(clientInterface);
}
class AudioPolicyCompatClient : public AudioPolicyClientInterface {
virtual void setParameters(audio_io_handle_t ioHandle,
const String8& keyValuePairs,
int delayMs = 0);
}
void AudioPolicyCompatClient::setParameters(audio_io_handle_t ioHandle,
const String8& keyValuePairs,
int delayMs)
{
mServiceOps->set_parameters(mService, ioHandle, keyValuePairs.string(),
delayMs);
}
struct audio_policy_service_ops aps_ops = {
open_output : aps_open_output,
open_duplicate_output : aps_open_dup_output,
close_output : aps_close_output,
suspend_output : aps_suspend_output,
restore_output : aps_restore_output,
open_input : aps_open_input,
close_input : aps_close_input,
set_stream_volume : aps_set_stream_volume,
set_stream_output : aps_set_stream_output,
set_parameters : aps_set_parameters,
get_parameters : aps_get_parameters,
start_tone : aps_start_tone,
stop_tone : aps_stop_tone,
set_voice_volume : aps_set_voice_volume,
move_effects : aps_move_effects,
load_hw_module : aps_load_hw_module,
open_output_on_module : aps_open_output_on_module,
open_input_on_module : aps_open_input_on_module,
};
static void aps_set_parameters(void *service, audio_io_handle_t io_handle,
const char *kv_pairs, int delay_ms)
{
AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
audioPolicyService->setParameters(io_handle, kv_pairs, delay_ms);
}
void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
const char *keyValuePairs,
int delayMs)
{
mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
delayMs);
}
status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs,
int delayMs)
{
status_t status = NO_ERROR;
AudioCommand *command = new AudioCommand();
command->mCommand = SET_PARAMETERS;
insertCommand_l(command, delayMs);
}
void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
{
case SET_PARAMETERS: {
}
mAudioCommands.insertAt(command, i + 1);
}
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
case SET_PARAMETERS: {
command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
}
}
status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
return af->setParameters(ioHandle, keyValuePairs);
}
status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
{
//AudioParameter paramRouting = AudioParameter(keyValuePairs);
String8 keyRouting = String8("routing");
int valueRouting;
AudioParameter param = AudioParameter(keyValuePairs);
int value;
if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
(value != 0)) {
for (size_t i = 0; i < mRecordThreads.size(); i++) {
mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
}
}
}
status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
{
mNewParameters.add(keyValuePairs);
}
const char * const AudioParameter::keyRouting = AUDIO_PARAMETER_STREAM_ROUTING;
bool AudioFlinger::MixerThread::checkForNewParameters_l()
{
status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
}
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out)
{
out->stream.common.set_parameters = out_set_parameters;
}
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
parms = str_parms_create_str(kvpairs);
ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
old_device = adev->devices; //HTC_AUD_ADD
adev->devices &= ~AUDIO_DEVICE_OUT_ALL;
adev->devices |= val;
out->devices = val;
ALOGW("out_set_parameters want to set devices:0x%x old_mode:%d new_mode:%d call_start:%d ",adev->devices,cur_mode,adev->mode,adev->call_start);
cur_mode = adev->mode;
}
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
ret = stream_routing_manager_create(adev);
}
static int stream_routing_manager_create(struct tiny_audio_device *adev)
{
/* create a thread to manager the device routing switch.*/
ret = pthread_create(&adev->routing_mgr.routing_switch_thread, NULL,
stream_routing_thread_entry, (void *)adev);
}
static void *stream_routing_thread_entry(void * param)
{
struct tiny_audio_device *adev = (struct tiny_audio_device *)param;
/* switch device routing here.*/
do_select_devices(adev);
return 0;
}
static void do_select_devices(struct tiny_audio_device *adev)
{
set_route_by_array(adev->mixer, adev->dev_cfgs[i].off,
adev->dev_cfgs[i].off_len);
}
static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
unsigned int len)
{
struct mixer_ctl *ctl;
unsigned int i, j, ret;
/* Go through the route array and set each value */
for (i = 0; i < len; i++) {
ctl = mixer_get_ctl_by_name(mixer, route[i].ctl_name);
if (!ctl) {
ALOGE("Unknown control '%s'\n", route[i].ctl_name);
continue;
}
if (route[i].strval) {
ret = mixer_ctl_set_enum_by_string(ctl, route[i].strval);
if (ret != 0) {
ALOGE("Failed to set '%s' to '%s'\n",
route[i].ctl_name, route[i].strval);
} else {
ALOGI("Set '%s' to '%s'\n",
route[i].ctl_name, route[i].strval);
}
} else {
/* This ensures multiple (i.e. stereo) values are set jointly */
for (j = 0; j < mixer_ctl_get_num_values(ctl); j++) {
ret = mixer_ctl_set_value(ctl, j, route[i].intval);
if (ret != 0) {
ALOGE("Failed to set '%s'.%d to %d\n",
route[i].ctl_name, j, route[i].intval);
} else {
ALOGI("Set '%s'.%d to %d\n",
route[i].ctl_name, j, route[i].intval);
}
}
}
}
return 0;
}
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
/* parse mixer ctl */
ret = adev_config_parse(adev);
}
static int adev_config_parse(struct tiny_audio_device *adev)
{
struct config_parse_state s;
FILE *f;
XML_Parser p;
char property[PROPERTY_VALUE_MAX];
char file[80];
int ret = 0;
bool eof = false;
int len;
//property_get("ro.product.device", property, "tiny_hw");
snprintf(file, sizeof(file), "/system/etc/%s", "tiny_hw.xml");
ALOGV("Reading configuration from %s\n", file);
f = fopen(file, "r");
if (!f) {
ALOGE("Failed to open %s\n", file);
return -ENODEV;
}
p = XML_ParserCreate(NULL);
if (!p) {
ALOGE("Failed to create XML parser\n");
ret = -ENOMEM;
goto out;
}
memset(&s, 0, sizeof(s));
s.adev = adev;
XML_SetUserData(p, &s);
XML_SetElementHandler(p, adev_config_start, adev_config_end);
while (!eof) {
len = fread(file, 1, sizeof(file), f);
if (ferror(f)) {
ALOGE("I/O error reading config\n");
ret = -EIO;
goto out_parser;
}
eof = feof(f);
if (XML_Parse(p, file, len, eof) == XML_STATUS_ERROR) {
ALOGE("Parse error at line %u:\n%s\n",
(unsigned int)XML_GetCurrentLineNumber(p),
XML_ErrorString(XML_GetErrorCode(p)));
ret = -EINVAL;
goto out_parser;
}
}
out_parser:
XML_ParserFree(p);
out:
fclose(f);
return ret;
}
static void adev_config_start(void *data, const XML_Char *elem,
const XML_Char **attr)
{
if (property_get(FM_DIGITAL_SUPPORT_PROPERTY, value, "0") && strcmp(value, "1") == 0)
{
dev_names = dev_names_digitalfm;
dev_num = sizeof(dev_names_digitalfm) / sizeof(dev_names_digitalfm[0]);
}
else
{
dev_names = dev_names_linein;
dev_num = sizeof(dev_names_linein) / sizeof(dev_names_linein[0]);
}
}
static const dev_names_para_t dev_names_linein[] = {
{ AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_FM_SPEAKER, "speaker" },
{ AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |AUDIO_DEVICE_OUT_FM_HEADSET,
"headphone" },
{ AUDIO_DEVICE_OUT_EARPIECE, "earpiece" },
/* ANLG for voice call via linein*/
{ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET | AUDIO_DEVICE_OUT_ALL_FM, "line" },
{ AUDIO_DEVICE_OUT_FM_HEADSET, "line-headphone" },
{ AUDIO_DEVICE_OUT_FM_SPEAKER, "line-speaker" },
{ AUDIO_DEVICE_IN_COMMUNICATION, "comms" },
{ AUDIO_DEVICE_IN_AMBIENT, "ambient" },
{ AUDIO_DEVICE_IN_BUILTIN_MIC, "builtin-mic" },
{ AUDIO_DEVICE_IN_WIRED_HEADSET, "headset-in" },
{ AUDIO_DEVICE_IN_AUX_DIGITAL, "digital" },
{ AUDIO_DEVICE_IN_BACK_MIC, "back-mic" },
//{ "linein-capture"},
};
static const dev_names_para_t dev_names_digitalfm[] = {
{ AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_FM_SPEAKER, "speaker" },
{ AUDIO_DEVICE_OUT_WIRED_HEADSET | AUDIO_DEVICE_OUT_WIRED_HEADPHONE |AUDIO_DEVICE_OUT_FM_HEADSET,
"headphone" },
{ AUDIO_DEVICE_OUT_EARPIECE, "earpiece" },
/* ANLG for voice call via linein*/
{ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "line" },
{ AUDIO_DEVICE_OUT_ALL_FM, "digital-fm" },
{ AUDIO_DEVICE_IN_COMMUNICATION, "comms" },
{ AUDIO_DEVICE_IN_AMBIENT, "ambient" },
{ AUDIO_DEVICE_IN_BUILTIN_MIC, "builtin-mic" },
{ AUDIO_DEVICE_IN_WIRED_HEADSET, "headset-in" },
{ AUDIO_DEVICE_IN_AUX_DIGITAL, "digital" },
{ AUDIO_DEVICE_IN_BACK_MIC, "back-mic" },
//{ "linein-capture"},
};
root@android:/system/etc # cat tiny_hw.xml
<!-- TinyHAL configuration file for GOD -->
<tinyalsa-audio device="SC8830 audio">
<!-- We are able to have most of our routing static so do that -->
<path>
<!-- DAC->Headphone -->
<ctl name="HPL Playback Volume" val="8" />
<ctl name="HPR Playback Volume" val="8" />
<ctl name="DACL Playback Volume" val="7" />
<ctl name="DACR Playback Volume" val="7" />
<!-- DAC->Speaker -->
<ctl name="SPKL Playback Volume" val="10" />
<ctl name="SPKR Playback Volume" val="10" />
<ctl name="DACL Playback Volume" val="5" />
<ctl name="DACR Playback Volume" val="5" />
<!-- DAC->Earpiece -->
<ctl name="EAR Playback Volume" val="10" />
<ctl name="DACL Playback Volume" val="5" />
<ctl name="DACR Playback Volume" val="5" />
<!-- ADC ->(main mic) -->
<ctl name="ADCL Capture Volume" val="12" />
<ctl name="ADCR Capture Volume" val="12" />
</path>
<!-- MUST NOT modify private field directly -->
<private name="vb control">
<func name="VBC Switch" val="arm" />
</private>
<private name="eq update">
<func name="VBC EQ Update" val="0" />
</private>
<private name="da eq switch">
<func name="VBC DA EQ Switch" val="0" />
</private>
<private name="ad01 eq switch">
<func name="VBC AD01 EQ Switch" val="0" />
</private>
<private name="ad23 eq switch">
<func name="VBC AD02 EQ Switch" val="0" />
</private>
<private name="da eq profile">
<func name="VBC DA EQ Profile Select" val="0" />
</private>
<private name="ad01 eq profile">
<func name="VBC AD01 EQ Profile Select" val="0" />
</private>
<private name="ad23 eq profile">
<func name="VBC AD23 EQ Profile Select" val="0" />
</private>
<private name="internal PA">
<func name="Inter PA Config" val="304" />
</private>
<device name="builtin-mic">
<path name="on">
<ctl name="ADCL Mixer MainMICADCL Switch" val="1" />
<ctl name="ADCR Mixer MainMICADCR Switch" val="1" />
<ctl name="Mic Function" val="1" />
</path>
<path name="off">
<ctl name="Mic Function" val="0" />
<ctl name="ADCL Mixer MainMICADCL Switch" val="0" />
<ctl name="ADCR Mixer MainMICADCR Switch" val="0" />
</path>
</device>
<device name="back-mic">
<path name="on">
<ctl name="ADCL Mixer AuxMICADCL Switch" val="1" />
<ctl name="ADCR Mixer AuxMICADCR Switch" val="1" />
<ctl name="Aux Mic Function" val="1" />
</path>
<path name="off">
<ctl name="Aux Mic Function" val="0" />
<ctl name="ADCL Mixer AuxMICADCL Switch" val="0" />
<ctl name="ADCR Mixer AuxMICADCR Switch" val="0" />
</path>
</device>
<device name="headset-in">
<path name="on">
<ctl name="ADCL Mixer HPMICADCL Switch" val="1" />
<ctl name="ADCR Mixer HPMICADCR Switch" val="1" />
<ctl name="HP Mic Function" val="1" />
</path>
<path name="off">
<ctl name="HP Mic Function" val="0" />
<ctl name="ADCL Mixer HPMICADCL Switch" val="0" />
<ctl name="ADCR Mixer HPMICADCR Switch" val="0" />
</path>
</device>
<device name="line-speaker">
<path name="on">
<ctl name="SPKL Mixer ADCLSPKL Switch" val="1" />
<ctl name="SPKL Mixer ADCRSPKL Switch" val="1" />
</path>
<path name="off">
<ctl name="SPKL Mixer ADCLSPKL Switch" val="0" />
<ctl name="SPKL Mixer ADCRSPKL Switch" val="0" />
</path>
</device>
<device name="line-headphone">
<path name="on">
<ctl name="HPL Mixer ADCRHPL Switch" val="1" />
<ctl name="HPR Mixer ADCLHPR Switch" val="1" />
</path>
<path name="off">
<ctl name="HPL Mixer ADCRHPL Switch" val="0" />
<ctl name="HPR Mixer ADCLHPR Switch" val="0" />
</path>
</device>
<device name="line">
<path name="on">
<ctl name="ADCL Mixer AILADCL Switch" val="1" />
<ctl name="ADCR Mixer AIRADCR Switch" val="1" />
<ctl name="Line Function" val="1" />
</path>
<path name="off">
<ctl name="Line Function" val="0" />
<ctl name="ADCL Mixer AILADCL Switch" val="0" />
<ctl name="ADCR Mixer AIRADCR Switch" val="0" />
</path>
</device>
<device name="digital-fm">
<path name="on">
<ctl name="Digital FM Function" val="1" />
<ctl name="AD IISMUX" val="2" />
</path>
<path name="off">
<ctl name="Digital FM Function" val="0" />
<ctl name="AD IISMUX" val="0" />
</path>
</device>
<device name="speaker">
<path name="on">
<ctl name="SPKR Mixer DACLSPKR Switch" val="1" />
<ctl name="SPKR Mixer DACRSPKR Switch" val="1" />
<ctl name="Speaker2 Function" val="1" />
</path>
<path name="off">
<ctl name="Speaker2 Function" val="0" />
<ctl name="SPKR Mixer DACLSPKR Switch" val="0" />
<ctl name="SPKR Mixer DACRSPKR Switch" val="0" />
</path>
</device>
<device name="headphone">
<path name="on">
<ctl name="HPR Mixer DACRHPR Switch" val="1" />
<ctl name="HPL Mixer DACLHPL Switch" val="1" />
<ctl name="HeadPhone Function" val="1" />
</path>
<path name="off">
<ctl name="HeadPhone Function" val="0" />
<ctl name="HPR Mixer DACRHPR Switch" val="0" />
<ctl name="HPL Mixer DACLHPL Switch" val="0" />
</path>
</device>
<device name="earpiece">
<path name="on">
<ctl name="Earpiece Function" val="1" />
</path>
<path name="off">
<ctl name="Earpiece Function" val="0" />
</path>
</device>
</tinyalsa-audio>