Android 音频源码分析——AudioTrack设备选择

Android 音频源码分析——AndroidRecord录音(一)
Android 音频源码分析——AndroidRecord录音(二)
Android 音频源码分析——AndroidRecord音频数据传输流程
Android 音频源码分析——audioserver启动
Android 音频源码分析——AudioFlinger
Android 音频源码分析——AudioTrack设备选择

基于Andorid9.0源码

以AudioTrack为例,梳理下输出设备选择流程。

音频设备选择的影响因素:

  1. AudioAttributes 声音流类型
  2. setForceUse 设置
  3. setPreferredDevice设置 (AudioRecord、AudioTrack、MediaRecorder、MediaPlayer)
  4. 等。。。。待研究

一、大多数情况输出设备选择

直接从AudioTrack.cpp 开始。

AudioTrack构造器  
》AudioTrack::set(){}
》AudioTrack::createTrack_l()
》audioFlinger->createTrack(input, output, &status);
》AudioFlinger::createTrack()
》AudioSystem::getOutputForAttr()
》AudioPolicyService::getOutputForAttr()
》AudioPolicyManager::getOutputForAttr()
status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
                                              audio_io_handle_t *output,
                                              audio_session_t session,
                                              audio_stream_type_t *stream,
                                              uid_t uid,
                                              const audio_config_t *config,
                                              audio_output_flags_t *flags,
                                              audio_port_handle_t *selectedDeviceId,
                                              audio_port_handle_t *portId)
{
    //获取stream type
    *stream = streamTypefromAttributesInt(&attributes)
    
    routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes)
        
    audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
    
    *output = getOutputForDevice(device, session, *stream, config, flags);    
}
  1. 通过AudioAttribute中的flags和usage获取对应的Stream type;
  2. AudioAttribute usage属性映射到strategy;
  3. 通过strategy 选择device类型;
  4. 选择音频设备、音频通路;

1. 获取stream type

通过flags和usage映射到 stream type

audio_stream_type_t AudioPolicyManager::streamTypefromAttributesInt(const audio_attributes_t *attr)
{
    // flags to stream type mapping
    if ((attr->flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
        return AUDIO_STREAM_ENFORCED_AUDIBLE;
    }
    if ((attr->flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
        return AUDIO_STREAM_BLUETOOTH_SCO;
    }
    if ((attr->flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
        return AUDIO_STREAM_TTS;
    }
    // usage to stream type mapping
    switch (attr->usage) {
    case AUDIO_USAGE_MEDIA:
    case AUDIO_USAGE_GAME:
    case AUDIO_USAGE_ASSISTANT:
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
        return AUDIO_STREAM_MUSIC;
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        return AUDIO_STREAM_ACCESSIBILITY;
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
        return AUDIO_STREAM_SYSTEM;
    case AUDIO_USAGE_VOICE_COMMUNICATION:
        return AUDIO_STREAM_VOICE_CALL;
    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
        return AUDIO_STREAM_DTMF;
    case AUDIO_USAGE_ALARM:
        return AUDIO_STREAM_ALARM;
    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
        return AUDIO_STREAM_RING;
    case AUDIO_USAGE_NOTIFICATION:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
    case AUDIO_USAGE_NOTIFICATION_EVENT:
        return AUDIO_STREAM_NOTIFICATION;
    case AUDIO_USAGE_UNKNOWN:
    default:
        return AUDIO_STREAM_MUSIC;
    }
}

2. 获取strategy

getStrategyForAttr会调到Engine的getStrategyForUsage函数

routing_strategy Engine::getStrategyForUsage(audio_usage_t usage)
{
    // usage to strategy mapping
    switch (usage) {
    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
        return STRATEGY_ACCESSIBILITY;
    case AUDIO_USAGE_MEDIA:
    case AUDIO_USAGE_GAME:
    case AUDIO_USAGE_ASSISTANT:
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
        return STRATEGY_MEDIA;
    case AUDIO_USAGE_VOICE_COMMUNICATION:
        return STRATEGY_PHONE;
    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
        return STRATEGY_DTMF;
    case AUDIO_USAGE_ALARM:
    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
        return STRATEGY_SONIFICATION;
    case AUDIO_USAGE_NOTIFICATION:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
    case AUDIO_USAGE_NOTIFICATION_EVENT:
        return STRATEGY_SONIFICATION_RESPECTFUL;
    case AUDIO_USAGE_UNKNOWN:
    default:
        return STRATEGY_MEDIA;
    }
}

AudioAttribute usage属性映射到strategy。

3. 获取设备类型

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
                                                         bool fromCache)
{
    // Check if an explicit routing request exists for a stream type corresponding to the
    // specified strategy and use it in priority over default routing rules.
    for (int stream = 0; stream < AUDIO_STREAM_FOR_POLICY_CNT; stream++) {
        if (getStrategy((audio_stream_type_t)stream) == strategy) {
            audio_devices_t forcedDevice =
                    mOutputRoutes.getActiveDeviceForStream(
                            (audio_stream_type_t)stream, mAvailableOutputDevices);
            if (forcedDevice != AUDIO_DEVICE_NONE) {
                return forcedDevice;
            }
        }
    }
    if (fromCache) {
        ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x",
              strategy, mDeviceForStrategy[strategy]);
        return mDeviceForStrategy[strategy];
    }
    return mEngine->getDeviceForStrategy(strategy);
}
  1. 检查是否存在与指定策略相对应的流类型的显示route请求,并优先于默认规则
  2. 是否从缓存中获取设备,这里framCache为false
  3. Engine中获取strategy对应的默认设备类型

Engine有两种:

frameworks/av/services/audioplicy/enginedefault/src/Engine.cpp 对应使用 audio_policy.conf

frameworks/av/services/audioplicy/engineconfigurable/src/Engine.cpp 对应使用 audio_policy_configuration.xml

这里以default为例,接着分析Engine中获取strategy对应的默认设备类型,代码较长,主要分析下STRATEGY_MEDIA 策略。

audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
{
    DeviceVector availableOutputDevices = mApmObserver->getAvailableOutputDevices();
    DeviceVector availableInputDevices = mApmObserver->getAvailableInputDevices();
    const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
    return getDeviceForStrategyInt(strategy, availableOutputDevices,
                                   availableInputDevices, outputs, (uint32_t)AUDIO_DEVICE_NONE);
}


audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy,
        DeviceVector availableOutputDevices,
        DeviceVector availableInputDevices,
        const SwAudioOutputCollection &outputs,
        uint32_t outputDeviceTypesToIgnore) const
{
	uint32_t device = AUDIO_DEVICE_NONE;
    uint32_t availableOutputDevicesType =
            availableOutputDevices.types() & ~outputDeviceTypesToIgnore;

    switch (strategy) {
    //省略。。。。。。
	case STRATEGY_MEDIA: {
        uint32_t device2 = AUDIO_DEVICE_NONE;
        if (strategy != STRATEGY_SONIFICATION) {
            // no sonification on remote submix (e.g. WFD)
            if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                                                 String8("0")) != 0) {
                device2 = availableOutputDevices.types() & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
            }
        }
        if (isInCall() && (strategy == STRATEGY_MEDIA)) {
            device = getDeviceForStrategyInt(
                    STRATEGY_PHONE, availableOutputDevices, availableInputDevices, outputs,
                    outputDeviceTypesToIgnore);
            break;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HEARING_AID;
        }
        if ((device2 == AUDIO_DEVICE_NONE) &&
                (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                 outputs.isA2dpSupported()) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
            if (device2 == AUDIO_DEVICE_NONE) {
                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
            }
            if (device2 == AUDIO_DEVICE_NONE) {
                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
            }
        }
        if ((device2 == AUDIO_DEVICE_NONE) &&
            (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
        }
        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
            // no sonification on aux digital (e.g. HDMI)
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
        }
        if ((device2 == AUDIO_DEVICE_NONE) &&
                (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
        }
        int device3 = AUDIO_DEVICE_NONE;
        if (strategy == STRATEGY_MEDIA) {
            // ARC, SPDIF and AUX_LINE can co-exist with others.
            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
        }

        device2 |= device3;
        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or
        // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise
        device |= device2;

        // If hdmi system audio mode is on, remove speaker out of output list.
        if ((strategy == STRATEGY_MEDIA) &&
            (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
        }

        // for STRATEGY_SONIFICATION:
        // if SPEAKER was selected, and SPEAKER_SAFE is available, use SPEAKER_SAFE instead
        if ((strategy == STRATEGY_SONIFICATION) &&
                (device & AUDIO_DEVICE_OUT_SPEAKER) &&
                (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
            device |= AUDIO_DEVICE_OUT_SPEAKER_SAFE;
            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
        }
        } break;
    }
    return device;
}
  1. 如果是拨打电话状态,并且strategy等于STRATEGY_MEDIA,重新调用getDeviceForStrategyInt,strategy使用STRATEGY_PHONE。

  2. 判断可用输出设备,优先判断A2dp相关是否可用;

    1. AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
    2. AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES(普通蓝牙耳机)
    3. AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER(蓝牙音箱)
    
  3. 判断用户是否强制设置AUDIO_POLICY_FORCE_SPEAKER 扬声器;

  4. 按优先级排序

    AUDIO_DEVICE_OUT_WIRED_HEADPHONE //普通 带线耳机
    AUDIO_DEVICE_OUT_LINE
    AUDIO_DEVICE_OUT_WIRED_HEADSET  //线控耳机
    AUDIO_DEVICE_OUT_USB_HEADSET   //usb耳机
    AUDIO_DEVICE_OUT_USB_ACCESSORY
    AUDIO_DEVICE_OUT_USB_DEVICE   //usb设备
    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET
    AUDIO_DEVICE_OUT_AUX_DIGITAL
    AUDIO_DEVICE_OUT_SPEAKER   //扬声器
    

4. 选择设备、通路

audio_io_handle_t AudioPolicyManager::getOutputForDevice(
        audio_devices_t device,
        audio_session_t session,
        audio_stream_type_t stream,
        const audio_config_t *config,
        audio_output_flags_t *flags)
{
    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
    //direct output 相关处理 ......
 	if ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
     	*flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
		 }
    //........
    
non_direct_output:
    // A request for HW A/V sync cannot fallback to a mixed output because time
    // stamps are embedded in audio data
    if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
        return AUDIO_IO_HANDLE_NONE;
    }

    // ignoring channel mask due to downmix capability in mixer

    // open a non direct output

    // for non direct outputs, only PCM is supported
    if (audio_is_linear_pcm(config->format)) {
        // get which output is suitable for the specified stream. The actual
        // routing change will happen when startOutput() will be called
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);

        // at this stage we should ignore the DIRECT flag as no direct output could be found earlier
        *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
        output = selectOutput(outputs, *flags, config->format);
    }

    return output;   
}

通过flag 进行选择音频通路, Mixer或Direct,通常不设置的话,是Mixer 类通路。

直接看non_direct_output部分

  1. 对于FLAG_HW_AV_SYNC 请求,不能回退到混合输出,因为音频数据中嵌入了时间戳;
  2. 对于非直接输出(non direct outputs),只支持PCM;
  3. getOutputsForDevice 获取哪个输出适合指定的流。 实际的路由更改将在调用startOutput()时发生;
  4. selectOutput 从一组中通过优先级选择一个;

接着看getOutputsForDevice

SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevice(
                                                                audio_devices_t device,
                                                                const SwAudioOutputCollection& openOutputs)
{
    SortedVector<audio_io_handle_t> outputs;

    ALOGVV("getOutputsForDevice() device %04x", device);
    for (size_t i = 0; i < openOutputs.size(); i++) {
        ALOGVV("output %zu isDuplicated=%d device=%04x",
                i, openOutputs.valueAt(i)->isDuplicated(),
                openOutputs.valueAt(i)->supportedDevices());
        if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
            ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i));
            outputs.add(openOutputs.keyAt(i));
        }
    }
    return outputs;
}

其中openOutputs是AudioPolicyManager::initialize加载hw module时进行添加的。通过遍历openOutputs,获取其支持对应device的所有audio_io_handle_t,并返回。

接着看selectOutput

audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
                                                       audio_output_flags_t flags,
                                                       audio_format_t format)
{
    // select one output among several that provide a path to a particular device or set of
    // devices (the list was previously build by getOutputsForDevice()).
    // The priority is as follows:
    // 1: the output with the highest number of requested policy flags
    // 2: the output with the bit depth the closest to the requested one
    // 3: the primary output
    // 4: the first output in the list
    if (outputs.size() == 0) {
        return AUDIO_IO_HANDLE_NONE;
    }
    if (outputs.size() == 1) {
        return outputs[0];
    }
    int maxCommonFlags = 0;
    audio_io_handle_t outputForFlags = AUDIO_IO_HANDLE_NONE;
    audio_io_handle_t outputForPrimary = AUDIO_IO_HANDLE_NONE;
    audio_io_handle_t outputForFormat = AUDIO_IO_HANDLE_NONE;
    audio_format_t bestFormat = AUDIO_FORMAT_INVALID;
    audio_format_t bestFormatForFlags = AUDIO_FORMAT_INVALID;

    for (audio_io_handle_t output : outputs) {
        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
        if (!outputDesc->isDuplicated()) {
            // if a valid format is specified, skip output if not compatible
            if (format != AUDIO_FORMAT_INVALID) {
                if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
                    if (format != outputDesc->mFormat) {
                        continue;
                    }
                } else if (!audio_is_linear_pcm(format)) {
                    continue;
                }
                if (AudioPort::isBetterFormatMatch(
                        outputDesc->mFormat, bestFormat, format)) {
                    outputForFormat = output;
                    bestFormat = outputDesc->mFormat;
                }
            }

            int commonFlags = popcount(outputDesc->mProfile->getFlags() & flags);
            if (commonFlags >= maxCommonFlags) {
                if (commonFlags == maxCommonFlags) {
                    if (format != AUDIO_FORMAT_INVALID
                            && AudioPort::isBetterFormatMatch(
                                    outputDesc->mFormat, bestFormatForFlags, format)) {
                        outputForFlags = output;
                        bestFormatForFlags = outputDesc->mFormat;
                    }
                } else {
                    outputForFlags = output;
                    maxCommonFlags = commonFlags;
                    bestFormatForFlags = outputDesc->mFormat;
                }
                ALOGV("selectOutput() commonFlags for output %d, %04x", output, commonFlags);
            }
            if (outputDesc->mProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                outputForPrimary = output;
            }
        }
    }

    if (outputForFlags != AUDIO_IO_HANDLE_NONE) {
        return outputForFlags;
    }
    if (outputForFormat != AUDIO_IO_HANDLE_NONE) {
        return outputForFormat;
    }
    if (outputForPrimary != AUDIO_IO_HANDLE_NONE) {
        return outputForPrimary;
    }

    return outputs[0];
}

在提供的特定一组输出设备中选择一个输出(该列表先前由getOutputsForDevice()构建)。
优先级如下:

  1. 请求的策略flag数量最多的output
  2. 位深度最接近请求值的output
  3. primary output
  4. 列表中的第一个output

getOutputForAttr 至此就选择好了所需要的设备。

二、setForceUse

上面有用到mForceUse,强制使用配置,其可以修改某些场景的设备优先级。

 // current forced use configuration
AudioSystem::forced_config mForceUse[AudioSystem::NUM_FORCE_USE]; 
/* device categories used for audio_policy->set_force_use()
 * These must match the values in AudioSystem.java
 */
typedef enum {
    AUDIO_POLICY_FORCE_NONE,
    AUDIO_POLICY_FORCE_SPEAKER,
    AUDIO_POLICY_FORCE_HEADPHONES,
    AUDIO_POLICY_FORCE_BT_SCO,
    AUDIO_POLICY_FORCE_BT_A2DP,
    AUDIO_POLICY_FORCE_WIRED_ACCESSORY,
    AUDIO_POLICY_FORCE_BT_CAR_DOCK,
    AUDIO_POLICY_FORCE_BT_DESK_DOCK,
    AUDIO_POLICY_FORCE_ANALOG_DOCK,
    AUDIO_POLICY_FORCE_DIGITAL_DOCK,
    AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */
    AUDIO_POLICY_FORCE_SYSTEM_ENFORCED,
    AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED,
    AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER,
    AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS,
    AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL,

    AUDIO_POLICY_FORCE_CFG_CNT,
    AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1,

    AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE,
} audio_policy_forced_cfg_t;

/* usages used for audio_policy->set_force_use()
 * These must match the values in AudioSystem.java
 */
typedef enum {
    AUDIO_POLICY_FORCE_FOR_COMMUNICATION,
    AUDIO_POLICY_FORCE_FOR_MEDIA,
    AUDIO_POLICY_FORCE_FOR_RECORD,
    AUDIO_POLICY_FORCE_FOR_DOCK,
    AUDIO_POLICY_FORCE_FOR_SYSTEM,
    AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO,
    AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND,
    AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING,

    AUDIO_POLICY_FORCE_USE_CNT,
    AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1,
} audio_policy_force_use_t;

AudioSystem.java 中setForceUse可以设置优先级,系统应用通常使用这个设置。

public static native int setForceUse(int usage, int config)

三、setPreferredDevice

Java层的AudioRecord、AudioTrack、MediaRecorder、MediaPlayer都有提供setPreferredDevice接口,通过此接口可以指定音频设备。

如:AudioTrack.java

/**
 * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
 * the output from this AudioTrack.
 * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink.
 *  If deviceInfo is null, default routing is restored.
 * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
 * does not correspond to a valid audio output device.
 */
@Override
public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
    // Do some validation....
    if (deviceInfo != null && !deviceInfo.isSink()) {
        return false;
    }
    int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
    boolean status = native_setOutputDevice(preferredDeviceId);
    if (status == true) {
        synchronized (this) {
            mPreferredDevice = deviceInfo;
        }
    }
    return status;
}

以AudioTrack为例分析下该接口

》AudioTrack.native_setOutputDevice(preferredDeviceId);android_media_AudioTrack_setOutputDevice(JNIEnv *env,  jobject thiz, jint device_id)
》status_t AudioTrack::setOutputDevice(audio_port_handle_t deviceId) {
    AutoMutex lock(mLock);
    if (mSelectedDeviceId != deviceId) {
        mSelectedDeviceId = deviceId;
        if (mStatus == NO_ERROR) {
            android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
            mProxy->interrupt();
        }
    }
    return NO_ERROR;
}
  1. 对比deviceid 不相同,则保存mSelectedDeviceId;
  2. 设置flags 为CBLK_INVALID;

之后会重新创建Track

》AudioTrack::restoreTrack_l(const char *from)createTrack_l()

AudioPolicyService根据状态、策略决定使用的音频设备。

你可能感兴趣的:(Android,音频,AudioTrack,音频设备,audio)