Android Audio 框架简读 <5>



前面讲到AudioFlinger打开设备,但是后面贴了图片就没继续了,现在继续看看:

audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module,
                                           audio_devices_t *pDevices,
                                           uint32_t *pSamplingRate,
                                           audio_format_t *pFormat,
                                           audio_channel_mask_t *pChannelMask,
                                           uint32_t *pLatencyMs,
                                           audio_output_flags_t flags)

就这个地方了!

准备打开如下:

outHwDev = findSuitableHwDev_l(module, *pDevices);
    if (outHwDev == NULL)
        return 0;

    audio_hw_device_t *hwDevHal = outHwDev->hwDevice();


先查找适合的设备,然后在打开,查找适合的设备如下:

AudioFlinger::AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
        audio_module_handle_t module,
        audio_devices_t devices)
{
    // if module is 0, the request comes from an old policy manager and we should load
    // well known modules
    if (module == 0) {
        ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
        for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
            loadHwModule_l(audio_interfaces[i]);
        }
        // then try to find a module supporting the requested device.
        for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
            AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(i);
            audio_hw_device_t *dev = audioHwDevice->hwDevice();
            if ((dev->get_supported_devices != NULL) &&
                    (dev->get_supported_devices(dev) & devices) == devices)
                return audioHwDevice;
        }
    } else {
        // check a match for the requested module handle
        AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(module);
        if (audioHwDevice != NULL) {
            return audioHwDevice;
        }
    }

    return NULL;
}

这个地方有两个遍历:

<1> : 遍历了所有的interfaces,这个接口非常的重要,就相当于通向不同设备的道路的大门,一般较多的AudioHardwareInterface,AudioHardwareA2dpInterface等等,使用不同的接口,就以为的操作不同的接口了!

<2> : 遍历了所有的设备,然后选择支持的设备返回,上面有name参考,打印出来即primary,a2dp,usb等等

然后通过上面返回的设备打开设备流:

status = hwDevHal->open_output_stream(hwDevHal,
                                          id,
                                          *pDevices,
                                          (audio_output_flags_t)flags,
                                          &config,
                                          &outStream);

然后创建播放线程:

if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
            (config.format != AUDIO_FORMAT_PCM_16_BIT) ||
            (config.channel_mask != AUDIO_CHANNEL_OUT_STEREO)) {
            thread = new DirectOutputThread(this, output, id, *pDevices);
            ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
        } else {
            thread = new MixerThread(this, output, id, *pDevices);
            ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
        }
        mPlaybackThreads.add(id, thread);


将穿件的播放线程添加到mPlaybackThreads中,AudioFlinger,创建好的线程会把该线程和它的Id保存在AudioFlinger的成员变量mPlaybackThreads 中,mPlaybackThreads是一个Vector,AudioFlinger创建的线程都会保存在里面,最后,openOutput返回该线程的 Id,该Id也就是所谓的audio_io_handle_t,AudioFlinger的调用者这能看到这个audio_io_handle_t,当需 要访问时传入该audio_io_handle_t,AudioFlinger会通过mPlaybackThreads,得到该线程的指针.所以可以每个播放都是拥有自己的播放线程的.

只有在音频数据处理上可能会MIXER.


下面来看看设备是如何切换的,比如蓝牙设备接入,并且要"替代"Speaker.

你可以从AudioManager.java调用setBluetoothA2dpOn开始看起,但是这里直接开始在AudioService.java看起:

/** @see AudioManager#setBluetoothA2dpOn() */
    public void setBluetoothA2dpOn(boolean on) {
        synchronized (mBluetoothA2dpEnabledLock) {
            mBluetoothA2dpEnabled = on;
            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
                    AudioSystem.FOR_MEDIA,
                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
                    null, 0);
        }
    }

一看这个sendMsg是需要mAudioHandler来处理的,那么mAudioHandler是如何处理的呢?

/** Handles internal volume messages in separate volume thread. */
    private class AudioHandler extends Handler {

        private void setDeviceVolume(VolumeStreamState streamState, int device) {

            // Apply volume
            streamState.applyDeviceVolume(device);

            // Apply change to all streams using this one as alias
            int numStreamTypes = AudioSystem.getNumStreamTypes();
            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
                if (streamType != streamState.mStreamType &&
                        mStreamVolumeAlias[streamType] == streamState.mStreamType) {
                    mStreamStates[streamType].applyDeviceVolume(getDeviceForStream(streamType));
                }
            }

            // Post a persist volume msg
            sendMsg(mAudioHandler,
                    MSG_PERSIST_VOLUME,
                    SENDMSG_QUEUE,
                    PERSIST_CURRENT|PERSIST_LAST_AUDIBLE,
                    device,
                    streamState,
                    PERSIST_DELAY);

        }
... ...


代码很多.上面的消息ID:MSG_SET_FORCE_BT_A2DP_USE,看一下上面Handler里面的:

case MSG_SET_FORCE_USE:
                case MSG_SET_FORCE_BT_A2DP_USE:
                    setForceUse(msg.arg1, msg.arg2);
                    break;

继续:

private void setForceUse(int usage, int config) {
            AudioSystem.setForceUse(usage, config);
        }


继续看AudioSystem.cpp中:

status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->setForceUse(usage, config);
}

上面终于获得的是AudioPolicyService这个服务进行切换设备的.继续看AudioPolicyService.cpp:

status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
                                         audio_policy_forced_cfg_t config)
{
    if (mpAudioPolicy == NULL) {
        return NO_INIT;
    }
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }
    if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
        return BAD_VALUE;
    }
    if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
        return BAD_VALUE;
    }
    ALOGV("setForceUse() tid %d", gettid());
    Mutex::Autolock _l(mLock);
    mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config);
    return NO_ERROR;
}

然后直接对应看audio_policy的HAL层:上面的set_force_use就对应下面的ap_set_force_use(为什么,可以看一下create_audio_policy函数)

 /* force using a specific device category for the specified usage */
static void ap_set_force_use(struct audio_policy *pol,
                          audio_policy_force_use_t usage,
                          audio_policy_forced_cfg_t config)
{
    struct legacy_audio_policy *lap = to_lap(pol);
    lap->apm->setForceUse((AudioSystem::force_use)usage,
                          (AudioSystem::forced_config)config);
}


上面apm是什么?

AudioPolicyInterface *apm;
lap->service_client =
        new AudioPolicyCompatClient(aps_ops, service);
    if (!lap->service_client) {
        ret = -ENOMEM;
        goto err_new_compat_client;
    }

    lap->apm = createAudioPolicyManager(lap->service_client);

在上面获取,最后跟踪在AudioPolicyManagerBase.cpp中:

void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)

看看下面:

checkA2dpSuspend();
    checkOutputForAllStrategies();
    updateDevicesAndOutputs();
    for (size_t i = 0; i < mOutputs.size(); i++) {
        audio_io_handle_t output = mOutputs.keyAt(i);
        audio_devices_t newDevice = getNewDevice(output, true /*fromCache*/);
        setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));
        if (forceVolumeReeval && (newDevice != AUDIO_DEVICE_NONE)) {
            applyStreamVolumes(output, newDevice, 0, true);
        }
    }

确认A2DP,后面的是修改策略等,注意下面的恢复A2DP的:

void AudioPolicyManagerBase::checkA2dpSuspend()

到后面的

setOutputDevice(output, newDevice, (newDevice != AUDIO_DEVICE_NONE));


下面来看看切换流程,假如设备插入耳机:

当耳机插入Android设备,那么与硬件直接打交道的linux核心层内部将会触发uevent或者inputevent事件:

<1> : 如果选择是uevent事件,那么在framework层将直接到WiredAccessoryService,然后给WiredAccessoryManager的notifyChanged处理;

<2> : 如果是inputevent事件,这个就需要先在InputManager中先被捕获,然后再转到WiredAccessoryManager中;

下面直接从notifySwitch开始:

    // Native callback.
    private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
        if (DEBUG) {
            Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
                    + ", mask=" + Integer.toHexString(switchMask));
        }

        if ((switchMask & SW_LID_BIT) != 0) {
            final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
            mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
        }

        if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
            mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
                    switchMask);
        }
    }


然后转入:

@Override
    public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
        if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
                + " bits=" + switchCodeToString(switchValues, switchMask)
                + " mask=" + Integer.toHexString(switchMask));

        synchronized (mLock) {
            int headset;
            mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
            switch (mSwitchValues & (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT)) {
                case 0:
                    headset = 0;
                    break;

                case SW_HEADPHONE_INSERT_BIT:
                    headset = BIT_HEADSET_NO_MIC;
                    break;

                case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:
                    headset = BIT_HEADSET;
                    break;

                case SW_MICROPHONE_INSERT_BIT:
                    headset = BIT_HEADSET;
                    break;

                default:
                    headset = 0;
                    break;
            }

            updateLocked(NAME_H2W, (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC)) | headset);
        }
    }

进入updateLocked

Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
                mHeadsetState, newName);
        mHandler.sendMessage(msg);

        mHeadsetState = headsetState;
    }

    private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_NEW_DEVICE_STATE:
                    setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
                    mWakeLock.release();
            }
        }
    };


看到setdeviceState中 :

private void setDevicesState(
            int headsetState, int prevHeadsetState, String headsetName) {
        synchronized (mLock) {
            int allHeadsets = SUPPORTED_HEADSETS;
            for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
                if ((curHeadset & allHeadsets) != 0) {
                    setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
                    allHeadsets &= ~curHeadset;
                }
            }
        }
    }

    private void setDeviceStateLocked(int headset,
            int headsetState, int prevHeadsetState, String headsetName) 

在setDeviceStateLocked中继续:

mAudioManager.setWiredDeviceConnectionState(device, state, headsetName);

看到这个了,是不是开始看到希望了,AudioManager是连接到AudioService的:

public void setWiredDeviceConnectionState(int device, int state, String name) {
        IAudioService service = getService();
        try {
            service.setWiredDeviceConnectionState(device, state, name);
        } catch (RemoteException e) {
            Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);
        }
    }

这一个转向是不是到了正轨了,下面就是AudioService:

public void setWiredDeviceConnectionState(int device, int state, String name) {
        synchronized (mConnectedDevices) {
            int delay = checkSendBecomingNoisyIntent(device, state);
            queueMsgUnderWakeLock(mAudioHandler,
                    MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
                    device,
                    state,
                    name,
                    delay);
        }
    }


一看,又看到mAudioHandler这个handler事件驱动了,上面已经大致介绍了,

case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
                    onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);
                    mMediaEventWakeLock.release();
                    break;

继续进入onSetWiredDevice....

handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
AudioSystem.setDeviceConnectionState(device,
                                                      AudioSystem.DEVICE_STATE_AVAILABLE,
                                                      params);


然后进入AudioSystem.cpp文件:

status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
                                               const char *device_address)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    const char *address = "";

    if (aps == 0) return PERMISSION_DENIED;

    if (device_address != NULL) {
        address = device_address;
    }

    return aps->setDeviceConnectionState(device, state, address);
}

看到了吧,终于见到AudioPolicyService了:

status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                  audio_policy_dev_state_t state,
                                                  const char *device_address)
{
    if (mpAudioPolicy == NULL) {
        return NO_INIT;
    }
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }
    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
        return BAD_VALUE;
    }
    if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
            state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
        return BAD_VALUE;
    }

    ALOGV("setDeviceConnectionState() tid %d", gettid());
    Mutex::Autolock _l(mLock);
    return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
                                                      state, device_address);
}

这个AudioPolicyService是打开audio_policy.default.so设备节点,那么就要看这个hal层了:

status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                  audio_policy_dev_state_t state,
                                                  const char *device_address)
{
    if (mpAudioPolicy == NULL) {
        return NO_INIT;
    }
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }
    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
        return BAD_VALUE;
    }
    if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
            state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
        return BAD_VALUE;
    }

    ALOGV("setDeviceConnectionState() tid %d", gettid());
    Mutex::Autolock _l(mLock);
    return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
                                                      state, device_address);
}

再看看里面的set_device_connection_state(...),到audio_hw_hal.cpp中:

对应:

lap->policy.set_device_connection_state = ap_set_device_connection_state;

那么再看看ap_set_device_connection_state函数:

static int ap_set_device_connection_state(struct audio_policy *pol,
                                          audio_devices_t device,
                                          audio_policy_dev_state_t state,
                                          const char *device_address)
{
    struct legacy_audio_policy *lap = to_lap(pol);
    return lap->apm->setDeviceConnectionState(
                    (AudioSystem::audio_devices)device,
                    (AudioSystem::device_connection_state)state,
                    device_address);
}

上面的apm在前面已经大致介绍了,一般是AudioPolicyManagerBase:

status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device,
                                                  AudioSystem::device_connection_state state,
                                                  const char *device_address)

如果上面不清楚为什么到AudioPolicyManagerBase,可以看一下:

lap->apm = createAudioPolicyManager(lap->service_client);

进入到这个类里面来了,阅读里面的代码,就可以衔接到前面的介绍了.

上面基本上就是整个切换流程,后面看一下蓝牙A2DP





你可能感兴趣的:(Android Audio 框架简读 <5>)