android audio

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>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值