IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Audio代码分析(7): AudioTrack create -> 正文阅读

[移动开发]Android Audio代码分析(7): AudioTrack create

java 层AudioTrack

legacy method 1:
? ? public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
? ? ? ? ? ? int bufferSizeInBytes, int mode) //这里的mode指的是static 还是stream
? ? throws IllegalArgumentException {
? ? ? ? this(streamType, sampleRateInHz, channelConfig, audioFormat,
? ? ? ? ? ? ? ? bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //ID_GENERATE 说的是native 分配一个session id
? ? }

legacy method 2: legacy method1 -> legacy method2 -> attribute way

? ? public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
? ? ? ? ? ? int bufferSizeInBytes, int mode, int sessionId)
? ? throws IllegalArgumentException {
? ? ? ? // mState already == STATE_UNINITIALIZED
? ? ? ? this((new AudioAttributes.Builder())
? ? ? ? ? ? ? ? ? ? .setLegacyStreamType(streamType)
? ? ? ? ? ? ? ? ? ? .build(),
? ? ? ? ? ? ? ? (new AudioFormat.Builder())
? ? ? ? ? ? ? ? ? ? .setChannelMask(channelConfig)
? ? ? ? ? ? ? ? ? ? .setEncoding(audioFormat)
? ? ? ? ? ? ? ? ? ? .setSampleRate(sampleRateInHz)
? ? ? ? ? ? ? ? ? ? .build(),
? ? ? ? ? ? ? ? bufferSizeInBytes,
? ? ? ? ? ? ? ? mode, sessionId);
? ? ? ? deprecateStreamTypeForPlayback(streamType, "AudioTrack", "AudioTrack()"); //提醒log
? ? }

attribure way 1

? ? public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
? ? ? ? ? ? int mode, int sessionId)
? ? ? ? ? ? ? ? ? ? throws IllegalArgumentException {
? ? ? ? this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/,
? ? ? ? ? ? ? ? ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */);
? ? }

最终实现方式
// encapsulationMode: indicates metadata encapsulation, 数据中有metadata不是纯净的pcm data
// TunerConfiguration: 说的是 used to convey tuner information?
// ? ? ? ? ? ? ? ? ? ? from the android.media.tv.Tuner API to AudioTrack construction.
// offload 说的是hardware直接处理

// 这三个参数默认(正常情况)都是false
? ? private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
? ? ? ? ? ? int mode, int sessionId, boolean offload, int encapsulationMode,
? ? ? ? ? ? @Nullable TunerConfiguration tunerConfiguration)
? ? ? ? ? ? ? ? ? ? throws IllegalArgumentException {

? ? ? ? // native initialization
? ? ? ? int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
? ? ? ? ? ? ? ? sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
? ? ? ? ? ? ? ? mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
? ? ? ? ? ? ? ? offload, encapsulationMode, tunerConfiguration,
? ? ? ? ? ? ? ? getCurrentOpPackageName());
? ? ? ? if (initResult != SUCCESS) {
? ? ? ? ? ? loge("Error code "+initResult+" when initializing AudioTrack.");
? ? ? ? ? ? return; // with mState == STATE_UNINITIALIZED
? ? ? ? }

? ? }

JNI level: native_setup

native_setup 创建native 层 AudioTrack 并set 赋值

1.?lpTrack = new AudioTrack(opPackageNameStr.c_str());

2.?lpTrack->set


frameworks/base/core/jni/android_media_AudioTrack.cpp
static const JNINativeMethod gMethods[] = {
? ? ? ? // name, ? ? ? ? ? ? ?signature, ? ? funcPtr
? ? ? ? {"native_setup",
? ? ? ? ?"(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
? ? ? ? ?(void *)android_media_AudioTrack_setup},
}

static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jobject jaa, jintArray jSampleRate,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jint channelPositionMask, jint channelIndexMask,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jint audioFormat, jint buffSizeInBytes, jint memoryMode,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jintArray jSession, jlong nativeAudioTrack,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jboolean offload, jint encapsulationMode,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jobject tunerConfiguration, jstring opPackageName) {
? ? ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
? ? ? ? ? " nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
? ? ? ? ? jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
? ? ? ? ? nativeAudioTrack, offload, encapsulationMode, tunerConfiguration);

? ? // if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one.
? ? sp<AudioTrack> lpTrack;
? ? if (nativeAudioTrack == 0) {

? ? ? ? // create the native AudioTrack object
? ? ? ? ScopedUtfChars opPackageNameStr(env, opPackageName);
? ? ? ? lpTrack = new AudioTrack(opPackageNameStr.c_str());

? ? ? ? // read the AudioAttributes values
? ? ? ? auto paa = JNIAudioAttributeHelper::makeUnique();
? ? ? ? jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
? ? ? ? ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
? ? ? ? ? ? ? ? paa->usage, paa->content_type, paa->flags, paa->tags);

? ? ? ? // initialize the native AudioTrack object
? ? ? ? status_t status = NO_ERROR;
? ? ? ? switch (memoryMode) {
? ? ? ? case MODE_STREAM:
? ? ? ? ? ? status = lpTrack->set(AUDIO_STREAM_DEFAULT,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// stream type, but more info conveyed
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // in paa (last argument)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sampleRateInHertz,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? format, // word length, PCM
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nativeChannelMask, offload ? 0 : frameCount,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? : AUDIO_OUTPUT_FLAG_NONE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audioCallback,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &(lpJniStorage->mCallbackData), // callback, callback data (user)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0, ? ?// notificationFrames == 0 since not using EVENT_MORE_DATA
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // to feed the AudioTrack
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0, ? ?// shared mem
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? true, // thread can call Java
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sessionId, // audio session ID
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? : AudioTrack::TRANSFER_SYNC,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? paa.get());
? ? ? ? ? ? break;
?? ?}
}

Native AudioTack

AudioTrack构造函数

frameworks/av/media/libaudioclient/AudioTrack.cpp
AudioTrack::AudioTrack(const std::string& opPackageName)
? ? : mStatus(NO_INIT),
? ? ? mState(STATE_STOPPED),
? ? ? mPreviousPriority(ANDROID_PRIORITY_NORMAL),
? ? ? mPreviousSchedulingGroup(SP_DEFAULT),
? ? ? mPausedPosition(0),
? ? ? mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
? ? ? mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
? ? ? mOpPackageName(opPackageName),
? ? ? mPauseTimeRealUs(0),
? ? ? mAudioTrackCallback(new AudioTrackCallback())
{
? ? mShootDetectWrapper = NULL;
? ? isAppSupported4D = false;
? ? mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
? ? mAttributes.usage = AUDIO_USAGE_UNKNOWN;
? ? mAttributes.flags = 0x0;
? ? strcpy(mAttributes.tags, "");
}

AudioTrack::set

status_t AudioTrack::set(
? ? ? ? audio_stream_type_t streamType,
? ? ? ? uint32_t sampleRate,
? ? ? ? audio_format_t format,
? ? ? ? audio_channel_mask_t channelMask,
? ? ? ? size_t frameCount,
? ? ? ? audio_output_flags_t flags,
? ? ? ? callback_t cbf,
? ? ? ? void* user,
? ? ? ? int32_t notificationFrames,
? ? ? ? const sp<IMemory>& sharedBuffer,
? ? ? ? bool threadCanCallJava,
? ? ? ? audio_session_t sessionId,
? ? ? ? transfer_type transferType,
? ? ? ? const audio_offload_info_t *offloadInfo,
? ? ? ? uid_t uid,
? ? ? ? pid_t pid,
? ? ? ? const audio_attributes_t* pAttributes,
? ? ? ? bool doNotReconnect,
? ? ? ? float maxRequiredSpeed,
? ? ? ? audio_port_handle_t selectedDeviceId)
{
? ? status_t status;
? ? uint32_t channelCount;
? ? pid_t callingPid;
? ? pid_t myPid;

? ? ALOGD("set(sessionId=%d)", sessionId);
? ? // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
? ? ALOGD("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
? ? ? ? ? "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
? ? ? ? ? __func__,
? ? ? ? ? streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
? ? ? ? ? sessionId, transferType, uid, pid);

? ?// AudioTrack Thread

? if (cbf != NULL) {
? ? ? ? mAudioTrackThread = new AudioTrackThread(*this);
? ? ? ? mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
? ? ? ? // thread begins in paused state, and will not reference us until start()
? ? }

? ? // create the IAudioTrack
? ? {
? ? ? ? AutoMutex lock(mLock);
? ? ? ? status = createTrack_l();
? ? }

}

AudioTrackThread


AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver)
? ? : Thread(true /* bCanCallJava */) ?// binder recursion on restoreTrack_l() may call Java.
? ? , mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
? ? ? mIgnoreNextPausedInt(false)
{
}

bool AudioTrack::AudioTrackThread::threadLoop() //对应的执行体
{
}

createTrack_l()

根据输入参数 CreateTrackInput 得到 CreateTrackOutput

status_t AudioTrack::createTrack_l()
{
? ? const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();

? ? IAudioFlinger::CreateTrackInput input;
? ? if (mStreamType != AUDIO_STREAM_DEFAULT) {
? ? ? ? input.attr = AudioSystem::streamTypeToAttributes(mStreamType);
? ? } else {
? ? ? ? input.attr = mAttributes;
? ? }
? ? input.config = AUDIO_CONFIG_INITIALIZER;
? ? input.config.sample_rate = mSampleRate;
? ? input.config.channel_mask = mChannelMask;
? ? input.config.format = mFormat;
? ? input.config.offload_info = mOffloadInfoCopy;
? ? input.clientInfo.clientUid = mClientUid;
? ? input.clientInfo.clientPid = mClientPid;
? ? input.clientInfo.clientTid = -1;

? ? input.flags = mFlags;
? ? input.frameCount = mReqFrameCount;
? ? input.notificationFrameCount = mNotificationFramesReq;
? ? input.selectedDeviceId = mSelectedDeviceId;
? ? input.sessionId = mSessionId;
? ? input.audioTrackCallback = mAudioTrackCallback;
? ? input.opPackageName = mOpPackageName;

? ? IAudioFlinger::CreateTrackOutput output;

? ? sp<IAudioTrack> track = audioFlinger->createTrack(input,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &status);

}

? ? /* CreateTrackInput contains all input arguments sent by AudioTrack to AudioFlinger
? ? ?* when calling createTrack() including arguments that will be updated by AudioFlinger
? ? ?* and returned in CreateTrackOutput object
? ? ?*/
? ? class CreateTrackInput : public Parcelable {
? ? ? ? /* input */
? ? ? ? audio_attributes_t attr;
? ? ? ? audio_config_t config;
? ? ? ? AudioClient clientInfo;
? ? ? ? sp<IMemory> sharedBuffer;
? ? ? ? uint32_t notificationsPerBuffer;
? ? ? ? float speed;
? ? ? ? sp<media::IAudioTrackCallback> audioTrackCallback;
? ? ? ? std::string opPackageName;

? ? ? ? /* input/output */
? ? ? ? audio_output_flags_t flags;
? ? ? ? size_t frameCount;
? ? ? ? size_t notificationFrameCount;
? ? ? ? audio_port_handle_t selectedDeviceId; // (mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE))
? ? ? ? audio_session_t sessionId;
? ? };

? ? /* CreateTrackOutput contains all output arguments returned by AudioFlinger to AudioTrack
? ? ?* when calling createTrack() including arguments that were passed as I/O for update by
? ? ?* CreateTrackInput.
? ? ?*/
? ? class CreateTrackOutput : public Parcelable {
? ? ? ? /* input/output */
? ? ? ? audio_output_flags_t flags;
? ? ? ? size_t frameCount;
? ? ? ? size_t notificationFrameCount;
? ? ? ? audio_port_handle_t selectedDeviceId; // (output.selectedDeviceId = input.selectedDeviceId;)
? ? ? ? audio_session_t sessionId;

? ? ? ? /* output */
? ? ? ? uint32_t sampleRate;
? ? ? ? size_t ? afFrameCount;
? ? ? ? uint32_t afSampleRate;
? ? ? ? uint32_t afLatencyMs;
? ? ? ? audio_io_handle_t outputId;
? ? ? ? audio_port_handle_t portId;
? ? };

audioFlinger->createTrack

AudioTack最终调用到audioFlinger IBinder的createTrack

audioFlinger client: createTrack


class BpAudioFlinger : public BpInterface<IAudioFlinger>
{

? ? virtual sp<IAudioTrack> createTrack(const CreateTrackInput& input,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CreateTrackOutput& output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? status_t *status)
? ? {
? ? ? ? Parcel data, reply;
? ? ? ? sp<IAudioTrack> track;
? ? ? ? data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());

? ? ? ? if (status == nullptr) {
? ? ? ? ? ? return track;
? ? ? ? }

? ? ? ? input.writeToParcel(&data);

? ? ? ? status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
? ? ? ? if (lStatus != NO_ERROR) {
? ? ? ? ? ? ALOGE("createTrack transaction error %d", lStatus);
? ? ? ? ? ? *status = DEAD_OBJECT;
? ? ? ? ? ? return track;
? ? ? ? }
? ? ? ? *status = reply.readInt32();
? ? ? ? if (*status != NO_ERROR) {
? ? ? ? ? ? ALOGE("createTrack returned error %d", *status);
? ? ? ? ? ? return track;
? ? ? ? }
? ? ? ? track = interface_cast<IAudioTrack>(reply.readStrongBinder());
? ? ? ? if (track == 0) {
? ? ? ? ? ? ALOGE("createTrack returned an NULL IAudioTrack with status OK");
? ? ? ? ? ? *status = DEAD_OBJECT;
? ? ? ? ? ? return track;
? ? ? ? }
? ? ? ? output.readFromParcel(&reply);
? ? ? ? return track;
? ? }
}

AudioFlinger Service: createTrack

status_t BnAudioFlinger::onTransact(
? ? uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
? ? switch (code) {
? ? ? ? case CREATE_TRACK: {
? ? ? ? ? ? CHECK_INTERFACE(IAudioFlinger, data, reply);

? ? ? ? ? ? CreateTrackInput input;
? ? ? ? ? ? if (input.readFromParcel((Parcel*)&data) != NO_ERROR) {
? ? ? ? ? ? ? ? reply->writeInt32(DEAD_OBJECT);
? ? ? ? ? ? ? ? return NO_ERROR;
? ? ? ? ? ? }

? ? ? ? ? ? status_t status;
? ? ? ? ? ? CreateTrackOutput output;

? ? ? ? ? ? sp<IAudioTrack> track= createTrack(input,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&status);

? ? ? ? ? ? LOG_ALWAYS_FATAL_IF((track != 0) != (status == NO_ERROR));
? ? ? ? ? ? reply->writeInt32(status);
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return NO_ERROR;
? ? ? ? ? ? }
? ? ? ? ? ? reply->writeStrongBinder(IInterface::asBinder(track));
? ? ? ? ? ? output.writeToParcel(reply);
? ? ? ? ? ? return NO_ERROR;
? ? ? ? } break;
}

AudioFlinger service createTrack的实现

frameworks/av/services/audioflinger/AudioFlinger.cpp

sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? CreateTrackOutput& output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? status_t *status)
{
? ? sp<PlaybackThread::Track> track;
? ? sp<TrackHandle> trackHandle;
? ? sp<Client> client;
? ? status_t lStatus;
? ? audio_stream_type_t streamType;
? ? audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
? ? std::vector<audio_io_handle_t> secondaryOutputs;

? ? // session的生成

? ? audio_session_t sessionId = input.sessionId;
? ? if (sessionId == AUDIO_SESSION_ALLOCATE) {
? ? ? ? sessionId = (audio_session_t) newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
? ? }

? ? //?AudioSystem::getOutputForAttr

? ? output.sessionId = sessionId;
? ? output.outputId = AUDIO_IO_HANDLE_NONE;
? ? output.selectedDeviceId = input.selectedDeviceId;
? ? lStatus = AudioSystem::getOutputForAttr(&localAttr, &output.outputId, sessionId, &streamType,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clientPid, clientUid, &input.config, input.flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &output.selectedDeviceId, &portId, &secondaryOutputs);

}

AudioSystem::getOutputForAttr


frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::getOutputForAttr(audio_attributes_t *attr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_io_handle_t *output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_session_t session,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_stream_type_t *stream,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid_t pid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uid_t uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const audio_config_t *config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_output_flags_t flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *selectedDeviceId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *portId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? std::vector<audio_io_handle_t> *secondaryOutputs)
{
? ? const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
? ? if (aps == 0) return NO_INIT;
? ? return aps->getOutputForAttr(attr, output, session, stream, pid, uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?flags, selectedDeviceId, portId, secondaryOutputs);
}

AudioPolicyService client 接口getOutputForAttr

frameworks/av/media/libaudioclient/IAudioPolicyService.cpp
? ? status_t getOutputForAttr(audio_attributes_t *attr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_io_handle_t *output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_session_t session,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_stream_type_t *stream,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid_t pid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uid_t uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const audio_config_t *config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_output_flags_t flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *selectedDeviceId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *portId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? std::vector<audio_io_handle_t> *secondaryOutputs) override
? ? ? ? {
? ? ? ? ? ? Parcel data, reply;
? ? ? ? ? ? data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
? ? ? ? ? ? data.write(attr, sizeof(audio_attributes_t));
? ? ? ? ? ? data.writeInt32(session);
? ? ? ? ? ? if (stream == NULL) {
? ? ? ? ? ? ? ? data.writeInt32(0);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? data.writeInt32(1);
? ? ? ? ? ? ? ? data.writeInt32(*stream);
? ? ? ? ? ? }
? ? ? ? ? ? data.writeInt32(pid);
? ? ? ? ? ? data.writeInt32(uid);
? ? ? ? ? ? data.write(config, sizeof(audio_config_t));
? ? ? ? ? ? data.writeInt32(static_cast <uint32_t>(flags));
? ? ? ? ? ? data.writeInt32(*selectedDeviceId);
? ? ? ? ? ? data.writeInt32(*portId);
? ? ? ? ? ? status_t status = remote()->transact(GET_OUTPUT_FOR_ATTR, data, &reply);
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return status;
? ? ? ? ? ? }
? ? ? ? ? ? status = (status_t)reply.readInt32();
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return status;
? ? ? ? ? ? }
? ? ? ? ? ? status = (status_t)reply.read(&attr, sizeof(audio_attributes_t));
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return status;
? ? ? ? ? ? }
? ? ? ? ? ? *output = (audio_io_handle_t)reply.readInt32();
? ? ? ? ? ? audio_stream_type_t lStream = (audio_stream_type_t)reply.readInt32();
? ? ? ? ? ? if (stream != NULL) {
? ? ? ? ? ? ? ? *stream = lStream;
? ? ? ? ? ? }
? ? ? ? ? ? *selectedDeviceId = (audio_port_handle_t)reply.readInt32();
? ? ? ? ? ? *portId = (audio_port_handle_t)reply.readInt32();
? ? ? ? ? ? secondaryOutputs->resize(reply.readInt32());
? ? ? ? ? ? return reply.read(secondaryOutputs->data(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? secondaryOutputs->size() * sizeof(audio_io_handle_t));
? ? ? ? }

AudioPolicyService service?接口getOutputForAttr实现


status_t BnAudioPolicyService::onTransact(
? ? uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
? ? ? ? case GET_OUTPUT_FOR_ATTR: {
? ? ? ? ? ? CHECK_INTERFACE(IAudioPolicyService, data, reply);
? ? ? ? ? ? audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
? ? ? ? ? ? status_t status = data.read(&attr, sizeof(audio_attributes_t));
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return status;
? ? ? ? ? ? }
? ? ? ? ? ? audio_session_t session = (audio_session_t)data.readInt32();
? ? ? ? ? ? audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
? ? ? ? ? ? bool hasStream = data.readInt32() != 0;
? ? ? ? ? ? if (hasStream) {
? ? ? ? ? ? ? ? stream = (audio_stream_type_t)data.readInt32();
? ? ? ? ? ? }
? ? ? ? ? ? pid_t pid = (pid_t)data.readInt32();
? ? ? ? ? ? uid_t uid = (uid_t)data.readInt32();
? ? ? ? ? ? audio_config_t config;
? ? ? ? ? ? memset(&config, 0, sizeof(audio_config_t));
? ? ? ? ? ? data.read(&config, sizeof(audio_config_t));
? ? ? ? ? ? audio_output_flags_t flags =
? ? ? ? ? ? ? ? ? ? static_cast <audio_output_flags_t>(data.readInt32());
? ? ? ? ? ? audio_port_handle_t selectedDeviceId = data.readInt32();
? ? ? ? ? ? audio_port_handle_t portId = (audio_port_handle_t)data.readInt32();
? ? ? ? ? ? audio_io_handle_t output = 0;
? ? ? ? ? ? std::vector<audio_io_handle_t> secondaryOutputs;

? ? ? ? ? ? status = AudioSanitizer::sanitizeAudioAttributes(&attr, "68953950");
? ? ? ? ? ? if (status == NO_ERROR) {
? ? ? ? ? ? ? ? status = getOutputForAttr(&attr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &output, session, &stream, pid, uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? flags, &selectedDeviceId, &portId, &secondaryOutputs);
? ? ? ? ? ? }
? ? ? ? ? ? reply->writeInt32(status);
? ? ? ? ? ? status = reply->write(&attr, sizeof(audio_attributes_t));
? ? ? ? ? ? if (status != NO_ERROR) {
? ? ? ? ? ? ? ? return status;
? ? ? ? ? ? }
? ? ? ? ? ? reply->writeInt32(output);
? ? ? ? ? ? reply->writeInt32(stream);
? ? ? ? ? ? reply->writeInt32(selectedDeviceId);
? ? ? ? ? ? reply->writeInt32(portId);
? ? ? ? ? ? reply->writeInt32(secondaryOutputs.size());
? ? ? ? ? ? return reply->write(secondaryOutputs.data(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? secondaryOutputs.size() * sizeof(audio_io_handle_t));
? ? ? ? } break;

}

status_t AudioPolicyService::getOutputForAttr(audio_attributes_t *attr,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_io_handle_t *output,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_session_t session,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_stream_type_t *stream,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid_t pid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uid_t uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const audio_config_t *config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_output_flags_t flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *selectedDeviceId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? audio_port_handle_t *portId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? std::vector<audio_io_handle_t> *secondaryOutputs)
{

? ? ALOGV("%s()", __func__);
? ? mLock.lock();
? ? sp<AudioPolicyEffects> audioPolicyEffects = mAudioPolicyEffects;
? ? mLock.unlock();
? ? audioPolicyEffects -> createGlobalEffects();
? ? Mutex::Autolock _l(mLock);

? ? const uid_t callingUid = IPCThreadState::self()->getCallingUid();
? ? if (!isAudioServerOrMediaServerUid(callingUid) || uid == (uid_t)-1) {
? ? ? ? ALOGW_IF(uid != (uid_t)-1 && uid != callingUid,
? ? ? ? ? ? ? ? "%s uid %d tried to pass itself off as %d", __func__, callingUid, uid);
? ? ? ? uid = callingUid;
? ? }
? ? if (!mPackageManager.allowPlaybackCapture(uid)) {
? ? ? ? attr->flags |= AUDIO_FLAG_NO_MEDIA_PROJECTION;
? ? }
? ? if (((attr->flags & (AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE)) != 0)
? ? ? ? ? ? && !bypassInterruptionPolicyAllowed(pid, uid)) {
? ? ? ? attr->flags &= ~(AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY|AUDIO_FLAG_BYPASS_MUTE);
? ? }
? ? AutoCallerClear acc;
? ? AudioPolicyInterface::output_type_t outputType;
? ? result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?config,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&flags, selectedDeviceId, portId,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?secondaryOutputs,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&outputType);

? ? // FIXME: Introduce a way to check for the the telephony device before opening the output
? ? if (result == NO_ERROR) {
? ? ? ? // enforce permission (if any) required for each type of input
? ? ? ? switch (outputType) {
? ? ? ? case AudioPolicyInterface::API_OUTPUT_LEGACY:
? ? ? ? ? ? break;
? ? ? ? case AudioPolicyInterface::API_OUTPUT_TELEPHONY_TX:
? ? ? ? ? ? if (!modifyPhoneStateAllowed(pid, uid)) {
? ? ? ? ? ? ? ? ALOGE("%s() permission denied: modify phone state not allowed for uid %d",
? ? ? ? ? ? ? ? ? ? __func__, uid);
? ? ? ? ? ? ? ? result = PERMISSION_DENIED;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? case AudioPolicyInterface::API_OUT_MIX_PLAYBACK:
? ? ? ? ? ? if (!modifyAudioRoutingAllowed(pid, uid)) {
? ? ? ? ? ? ? ? ALOGE("%s() permission denied: modify audio routing not allowed for uid %d",
? ? ? ? ? ? ? ? ? ? __func__, uid);
? ? ? ? ? ? ? ? result = PERMISSION_DENIED;
? ? ? ? ? ? }
? ? ? ? ? ? break;
? ? ? ? case AudioPolicyInterface::API_OUTPUT_INVALID:
? ? ? ? default:
? ? ? ? ? ? LOG_ALWAYS_FATAL("%s() encountered an invalid output type %d",
? ? ? ? ? ? ? ? __func__, (int)outputType);
? ? ? ? }
? ? }

? ? if (result == NO_ERROR) {
? ? ? ? sp <AudioPlaybackClient> client =
? ? ? ? ? ? new AudioPlaybackClient(*attr, *output, uid, pid, session, *portId, *selectedDeviceId, *stream);
? ? ? ? mAudioPlaybackClients.add(*portId, client);
? ? }
? ? return result;
}

AudioPolicyService getOutputForAttr 由APM 实现


frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
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,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? std::vector<audio_io_handle_t> *secondaryOutputs,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? output_type_t *outputType)
{
? ? // The supplied portId must be AUDIO_PORT_HANDLE_NONE
? ? if (*portId != AUDIO_PORT_HANDLE_NONE) {
? ? ? ? return INVALID_OPERATION;
? ? }
? ? const audio_port_handle_t requestedPortId = *selectedDeviceId;
? ? audio_attributes_t resultAttr;
? ? bool isRequestedDeviceForExclusiveUse = false;
? ? std::vector<sp<AudioPolicyMix>> secondaryMixes;
? ? const sp<DeviceDescriptor> requestedDevice =
? ? ? mAvailableOutputDevices.getDeviceFromId(requestedPortId);

? ? // Prevent from storing invalid requested device id in clients
? ? const audio_port_handle_t sanitizedRequestedPortId =
? ? ? requestedDevice != nullptr ? requestedPortId : AUDIO_PORT_HANDLE_NONE;
? ? *selectedDeviceId = sanitizedRequestedPortId;

? ? callingAppuid = uid;
? ? callingAppName = getPackageName(uid);
? ? audio_app_type_f appType = getAppMaskByName(callingAppName);

? ? status_t status = getOutputForAttrInt(&resultAttr, output, session, attr, stream, uid,
? ? ? ? ? ? config, flags, selectedDeviceId, &isRequestedDeviceForExclusiveUse,
? ? ? ? ? ? secondaryOutputs != nullptr ? &secondaryMixes : nullptr, outputType);
? ? if (status != NO_ERROR) {
? ? ? ? return status;
? ? }
? ? std::vector<wp<SwAudioOutputDescriptor>> weakSecondaryOutputDescs;
? ? if (secondaryOutputs != nullptr) {
? ? ? ? for (auto &secondaryMix : secondaryMixes) {
? ? ? ? ? ? sp<SwAudioOutputDescriptor> outputDesc = secondaryMix->getOutput();
? ? ? ? ? ? if (outputDesc != nullptr &&
? ? ? ? ? ? ? ? outputDesc->mIoHandle != AUDIO_IO_HANDLE_NONE) {
? ? ? ? ? ? ? ? secondaryOutputs->push_back(outputDesc->mIoHandle);
? ? ? ? ? ? ? ? weakSecondaryOutputDescs.push_back(outputDesc);
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ? audio_config_base_t clientConfig = {.sample_rate = config->sample_rate,
? ? ? ? .channel_mask = config->channel_mask,
? ? ? ? .format = config->format,
? ? };
? ? *portId = PolicyAudioPort::getNextUniqueId();

? ? sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
? ? sp<TrackClientDescriptor> clientDesc =
? ? ? ? new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sanitizedRequestedPortId, *stream,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mEngine->getProductStrategyForAttributes(resultAttr),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? toVolumeSource(resultAttr),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *flags, isRequestedDeviceForExclusiveUse,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? std::move(weakSecondaryOutputDescs),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? outputDesc->mPolicyMix);
? ? outputDesc->addClient(clientDesc);

? ? clientDesc->setAppName(String8(callingAppName));
? ? outputDesc->setAppMask(appType); //output
? ? clientDesc->setAppMask(appType); //output

? ? if ((attr->content_type == AUDIO_CONTENT_TYPE_SONIFICATION) &&
? ? ? ? (attr->usage == AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE) &&
? ? ? ? (*stream == AUDIO_STREAM_RING)) {
? ? ? ? mpClientInterface->setParameters(outputDesc->mIoHandle, String8("output_for_sing"));
? ? }

? ? ALOGD("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
? ? ? ? ? *output, requestedPortId, *selectedDeviceId, *portId);

? ? return NO_ERROR;
}

AudioPolicyManager::getOutputForAttrInt

只关注getOutputForAttrInt部分,这是最终选择device的关键部分,policy的最终体现

status_t AudioPolicyManager::getOutputForAttrInt(
? ? ? ? audio_attributes_t *resultAttr,
? ? ? ? audio_io_handle_t *output,
? ? ? ? audio_session_t session,
? ? ? ? const audio_attributes_t *attr,
? ? ? ? audio_stream_type_t *stream,
? ? ? ? uid_t uid,
? ? ? ? const audio_config_t *config,
? ? ? ? audio_output_flags_t *flags,
? ? ? ? audio_port_handle_t *selectedDeviceId,
? ? ? ? bool *isRequestedDeviceForExclusiveUse,
? ? ? ? std::vector<sp<AudioPolicyMix>> *secondaryMixes,
? ? ? ? output_type_t *outputType)
{
? ? DeviceVector outputDevices;
? ? const audio_port_handle_t requestedPortId = *selectedDeviceId;
? ? DeviceVector msdDevices = getMsdAudioOutDevices();
? ? const sp<DeviceDescriptor> requestedDevice =
? ? ? ? mAvailableOutputDevices.getDeviceFromId(requestedPortId);
? ? *outputType = API_OUTPUT_INVALID;

? ? status_t status = getAudioAttributes(resultAttr, attr, *stream);

? ? // [1]:?mEngine->getStreamTypeForAttributes
? ? *stream = mEngine->getStreamTypeForAttributes(*resultAttr);

? ? // 输入请求参数
? ? ALOGD("%s()+ attributes=%s stream=%s session %d output %d selectedDeviceId %d device %s sampling rate %d format %#x"
? ? ? ? "channel mask %#x flags %#x stream %s uid %d",
? ? ? ? ? ? ?__func__, toString(*resultAttr).c_str(), toString(*stream).c_str(), session, *output,
? ? ? ? ? ? ? ? ? ? requestedPortId, outputDevices.toString().c_str(), config->sample_rate, config->format,
? ? ? ? ? ? ? ? ? ? ? ? ? ? config->channel_mask, *flags, toString(*stream).c_str(), uid);

? ? // [2]:?mEngine->getOutputDevicesForAttributes

? ? outputDevices = mEngine->getOutputDevicesForAttributes(*resultAttr, requestedDevice, false);

? // 选择到一组devices

? ? ALOGV("%s() device %s, sampling rate %d, format %#x, channel mask %#x, flags %#x stream %s",
? ? ? ? ? __func__, outputDevices.toString().c_str(), config->sample_rate, config->format,
? ? ? ? ? config->channel_mask, *flags, toString(*stream).c_str());

? ? *output = AUDIO_IO_HANDLE_NONE;
? ? if (*output == AUDIO_IO_HANDLE_NONE) {

? ? ?// [3]? getOutputForDevices
? ? ? ? *output = getOutputForDevices(outputDevices, session, *stream, config,
? ? ? ? ? ? ? ? flags, resultAttr->flags & AUDIO_FLAG_MUTE_HAPTIC);
? ? }

? ? *selectedDeviceId = getFirstDeviceId(outputDevices);

// 选择一个Device
? ? ALOGD("%s()- attributes=%s stream=%s session %d output %d selectedDeviceId %d device %s sampling rate %d format %#x"
? ? ? ? "channel mask %#x flags %#x stream %s uid %d",
? ? ? ? ? ? ?__func__, toString(*resultAttr).c_str(), toString(*stream).c_str(), session, *output,
? ? ? ? ? ? ? ? ? ? requestedPortId, outputDevices.toString().c_str(), config->sample_rate, config->format,
? ? ? ? ? ? ? ? ? ? ? ? ? ? config->channel_mask, *flags, toString(*stream).c_str(), uid);
? ? return NO_ERROR;
}

mEngine->getStreamTypeForAttributes
?

audio_stream_type_t EngineBase::getStreamTypeForAttributes(const audio_attributes_t &attr) const
{
? ? return mProductStrategies.getStreamTypeForAttributes(attr);
}

audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
? ? ? ? const audio_attributes_t &attr) const
{
? ? const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?[&attr](const auto &supportedAttr) {
? ? ? ? return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });

? ? audio_stream_type_t streamType = iter->mStream;
? ? return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
}

bool AudioProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const audio_attributes_t clientAttritubes)
{
? ? return ((refAttributes.usage == AUDIO_USAGE_UNKNOWN) ||
? ? ? ? ? ? (clientAttritubes.usage == refAttributes.usage)) &&
? ? ? ? ? ? ((refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) ||
? ? ? ? ? ? ?(clientAttritubes.content_type == refAttributes.content_type)) &&
? ? ? ? ? ? ((refAttributes.flags == AUDIO_FLAG_NONE) ||
? ? ? ? ? ? ?(clientAttritubes.flags != AUDIO_FLAG_NONE &&
? ? ? ? ? ? (clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) &&
? ? ? ? ? ? ((strlen(refAttributes.tags) == 0) ||
? ? ? ? ? ? ?(std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0));
}
?

getOutputDevicesForAttributes

根据Attributes 得到Devices由两种方式:1. findPrefferredDevice,

2. getDevicesForProductStrategy (这里忽略了mDevicesForStrategies.at(strategy))

findPrefferredDevice没有看懂,这里主要分析 getDevicesForProductStrategy

DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const sp<DeviceDescriptor> &preferredDevice,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?bool fromCache) const
{
? ? // First check for explict routing device, 显示routing 设备
? ? if (preferredDevice != nullptr) {
? ? ? ? ALOGV("%s explicit Routing on device %s", __func__, preferredDevice->toString().c_str());
? ? ? ? return DeviceVector(preferredDevice);
? ? }
? ? product_strategy_t strategy = getProductStrategyForAttributes(attributes);
? ? const DeviceVector availableOutputDevices =

? ? ? ? ? ? ? ? ? ? ? ?getApmObserver()->getAvailableOutputDevices();
? ? const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
? ? //
? ? // Honor explicit routing requests only if all active clients have a preferred route in which
? ? // case the last active client route is used
? ? sp<DeviceDescriptor> device = findPreferredDevice(outputs,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?strategy,?availableOutputDevices);
? ? if (device != nullptr) {
? ? ? ? return DeviceVector(device);
? ? }

? ? return fromCache?

? ? ? ? ? ? ? mDevicesForStrategies.at(strategy) : getDevicesForProductStrategy(strategy);
}

findPreferredDevice

没看懂怎么找到 preferredDevice的

class DeviceVector : public SortedVector<sp<DeviceDescriptor> >
{
}
// 描述DevicePort
class DeviceDescriptor : public DeviceDescriptorBase,
? ? ? ? ? ? ? ? ? ? ? ? ?public PolicyAudioPort, public PolicyAudioPortConfig
{
private:
? ? std::string mTagName; // Unique human readable identifier for a device port found in conf file.
? ? FormatVector ? ? ? ?mEncodedFormats;
? ? audio_format_t ? ? ?mCurrentEncodedFormat;
}

class SwAudioOutputCollection :
? ? ? ? public DefaultKeyedVector< audio_io_handle_t, sp<SwAudioOutputDescriptor> >
{
}

// Audio output driven by a software mixer in audio flinger.
class SwAudioOutputDescriptor: public AudioOutputDescriptor
{
}

// Audio output driven by an input device directly.
class HwAudioOutputDescriptor: public AudioOutputDescriptor
{
}

// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig,
? ? ? ? public PolicyAudioPortConfig,
? ? ? ? public AudioIODescriptorInterface,
? ? ? ? public ClientMapHandler<TrackClientDescriptor>
{
}

getDevicesForProductStrategy

getDevicesForProductStrategy 有两种方式:1. 直接从getPreferredDeviceForStrategy得到

2.??getDevicesForStrategyInt 根据strategy类型去选择

DeviceVector Engine::getDevicesForProductStrategy(product_strategy_t strategy) const {
? ? DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();

? ? //[1] check if this strategy has a preferred device that is available,
? ? // if yes, give priority to it
? ? AudioDeviceTypeAddr preferredStrategyDevice;
? ? const status_t status = getPreferredDeviceForStrategy(strategy, preferredStrategyDevice);
? ? if (status == NO_ERROR) {
? ? ? ? // there is a preferred device, is it available?
? ? ? ? sp<DeviceDescriptor> preferredAvailableDevDescr = availableOutputDevices.getDevice(
? ? ? ? ? ? ? ? preferredStrategyDevice.mType,
? ? ? ? ? ? ? ? String8(preferredStrategyDevice.mAddress.c_str()),
? ? ? ? ? ? ? ? AUDIO_FORMAT_DEFAULT);
? ? ? ? if (preferredAvailableDevDescr != nullptr) {
? ? ? ? ? ? ALOGVV("%s using pref device 0x%08x/%s for strategy %u",
? ? ? ? ? ? ? ? ? ?__func__, preferredStrategyDevice.mType,
? ? ? ? ? ? ? ? ? ?preferredStrategyDevice.mAddress.c_str(), strategy);
? ? ? ? ? ? return DeviceVector(preferredAvailableDevDescr);
? ? ? ? }
? ? }

? ? //[2] legacyStrategy
? ? DeviceVector availableInputDevices = getApmObserver()->getAvailableInputDevices();
? ? const SwAudioOutputCollection& outputs = getApmObserver()->getOutputs();
? ? auto legacyStrategy = mLegacyStrategyMap.find(strategy) != end(mLegacyStrategyMap) ?
? ? ? ? ? ? ? ? ? ? ? ? ? mLegacyStrategyMap.at(strategy) : STRATEGY_NONE;
? ? return getDevicesForStrategyInt(legacyStrategy,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? availableOutputDevices,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? availableInputDevices, outputs);
}

[1] getPreferredDeviceForStrategy(strategy, preferredStrategyDevice)


// EngineBase::setPreferredDeviceForStrategy
// (product_strategy_t strategy, const AudioDeviceTypeAddr &device)
// 策略和Device的对应关系

status_t EngineBase::getPreferredDeviceForStrategy(product_strategy_t strategy,
? ? ? ? ? ? AudioDeviceTypeAddr &device) const
{
? ? // verify strategy exists
? ? if (mProductStrategies.find(strategy) == mProductStrategies.end()) {
? ? ? ? ALOGE("%s unknown strategy %u", __func__, strategy);
? ? ? ? return BAD_VALUE;
? ? }
? ? // preferred device for this strategy?
? ? auto devIt = mProductStrategyPreferredDevices.find(strategy);
? ? if (devIt == mProductStrategyPreferredDevices.end()) {
? ? ? ? ALOGV("%s no preferred device for strategy %u", __func__, strategy);
? ? ? ? return NAME_NOT_FOUND;
? ? }

? ? device = devIt->second;
? ? return NO_ERROR;
}

class ProductStrategyPreferredRoutingMap : public std::map<product_strategy_t, AudioDeviceTypeAddr>
{
public:
? ? void dump(String8 *dst, int spaces = 0) const;
};

//[2] getDevicesForStrategyInt?:mLegacyStrategyMap


struct legacy_strategy_map { const char *name; legacy_strategy id; };
static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
? ? static const std::vector<legacy_strategy_map> legacyStrategy = {
? ? ? ? { "STRATEGY_NONE", STRATEGY_NONE },
? ? ? ? { "STRATEGY_MEDIA", STRATEGY_MEDIA },
? ? ? ? { "STRATEGY_PHONE", STRATEGY_PHONE },
? ? ? ? { "STRATEGY_SONIFICATION", STRATEGY_SONIFICATION },
? ? ? ? { "STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL },
? ? ? ? { "STRATEGY_DTMF", STRATEGY_DTMF },
? ? ? ? { "STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE },
? ? ? ? { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
? ? ? ? { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
? ? ? ? { "STRATEGY_REROUTING", STRATEGY_REROUTING },
? ? ? ? { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
? ? ? ? { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
? ? };
? ? return legacyStrategy;
}

getDevicesForStrategyInt:

代码的逻辑很简单switch 遍历strategy, 通过getDevicesFromType 找到devices
DeviceVector Engine::getDevicesForStrategyInt(legacy_strategy strategy,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DeviceVector availableOutputDevices,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DeviceVector availableInputDevices,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const SwAudioOutputCollection &outputs) const
{
? ?DeviceVector devices;
? ?
? ?switch (strategy) {
? ?
? ?case ?STRATEGY_MEDIA: {
? ? ? ? DeviceVector devices2;
? ? ? ? if ((devices2.isEmpty()) &&
? ? ? ? ? ? ? ? (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) != AUDIO_POLICY_FORCE_NO_BT_A2DP)) {
? ? ? ? ? ? devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_HEARING_AID);
? ? ? ? }
? ? ? ? if ((devices2.isEmpty()) &&
? ? ? ? ? ? (getForceUse(AUDIO_POLICY_FORCE_FOR_MEDIA) == AUDIO_POLICY_FORCE_SPEAKER)) {
? ? ? ? ? ? devices2 = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_SPEAKER);
? ? ? ? }

? ?}

? ? if (devices.isEmpty()) {
? ? ? ? ALOGV("getDevicesForStrategy() no device found for strategy %d", strategy);
? ? ? ? sp<DeviceDescriptor> defaultOutputDevice = getApmObserver()->getDefaultOutputDevice();
? ? ? ? if (defaultOutputDevice != nullptr) {
? ? ? ? ? ? devices.add(defaultOutputDevice);
? ? ? ? }
? ? ? ? ALOGE_IF(devices.isEmpty(),
? ? ? ? ? ? ? ? ?"getDevicesForStrategy() no default device defined");
? ? }

? ? // 输出的log

? ? ALOGV("getDevices ForStrategy() strategy %d, device %s",
? ? ? ? ? ?strategy, dumpDeviceTypes(devices.types()).c_str());
? ? return devices;
}
?

上面我们根据attribute已经找到一组 devices, 还没有使用具体的信息如sample rate, format等等

getOutputForDevices 从Devices 中根据sample rate等具体信息根据策略配置得到bestDevice.

getOutputForDevices

audio_io_handle_t AudioPolicyManager::getOutputForDevices(
? ? ? ? const DeviceVector &devices,
? ? ? ? audio_session_t session,
? ? ? ? audio_stream_type_t stream,
? ? ? ? const audio_config_t *config,
? ? ? ? audio_output_flags_t *flags,
? ? ? ? bool forceMutingHaptic)
{
? ? audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;

//[1] 对 flag的特殊处理
? ? // Discard haptic channel mask when forcing muting haptic channels.
? ? audio_channel_mask_t channelMask = forceMutingHaptic
? ? ? ? ? ? ? (config->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL) : config->channel_mask;

? ? // open a direct output if required by specified parameters
? ? //force direct flag if offload flag is set: offloading implies a direct output stream
? ? // and all common behaviors are driven by checking only the direct flag
? ? // this should normally be set appropriately in the policy configuration file
? ? if ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
? ? ? ? *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
? ? }
? ? if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
? ? ? ? *flags = (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT);
? ? }
? ? // only allow deep buffering for music stream type
? ? if (stream != AUDIO_STREAM_MUSIC) {
? ? ? ? *flags = (audio_output_flags_t)(*flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
? ? } else if (/* stream == AUDIO_STREAM_MUSIC && */
? ? ? ? ? ? *flags == AUDIO_OUTPUT_FLAG_NONE &&
? ? ? ? ? ? property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
? ? ? ? // use DEEP_BUFFER as default output for music stream type
? ? ? ? *flags = (audio_output_flags_t)AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
? ? }
? ? if (stream == AUDIO_STREAM_TTS) {
? ? ? ? *flags = AUDIO_OUTPUT_FLAG_TTS;
? ? } else if (stream == AUDIO_STREAM_VOICE_CALL &&
? ? ? ? ? ? ? ?audio_is_linear_pcm(config->format) &&
? ? ? ? ? ? ? ?(*flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) == 0) {
? ? ? ? *flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_VOIP_RX |
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AUDIO_OUTPUT_FLAG_DIRECT);
? ? ? ? ALOGV("Set VoIP and Direct output flags for PCM format");
? ? }

//[2]?openDirectOutput,没有 direct flag也需要openDirectOutput?
? ? audio_config_t directConfig = *config;
? ? directConfig.channel_mask = channelMask;
? ? status_t status = openDirectOutput(stream, session, &directConfig, *flags, devices, &output);
? ? if (status != NAME_NOT_FOUND) {
? ? ? ? return 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

//[3] 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 = getOutputsForDevices(devices, 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, channelMask, config->sample_rate);
? ? }
? ? ALOGW_IF((output == 0), "getOutputForDevices() could not find output for stream %d, "
? ? ? ? ? ? "sampling rate %d, format %#x, channels %#x, flags %#x",
? ? ? ? ? ? stream, config->sample_rate, config->format, channelMask, *flags);

? ? return output;
}

这里主要关注audio_is_linear_pcm, 其中包括getOutputsForDevices,?selectOutput

SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);

getOutputsForDevices

从openOuputs中得到 DeviceVector

SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
? ? ? ? ? ? const DeviceVector &devices,
? ? ? ? ? ? const SwAudioOutputCollection& openOutputs)
{
? ? SortedVector<audio_io_handle_t> outputs;

? ? ALOGVV("%s() devices %s", __func__, devices.toString().c_str());
? ? for (size_t i = 0; i < openOutputs.size(); i++) {
? ? ? ? ALOGVV("output %zu isDuplicated=%d device=%s",
? ? ? ? ? ? ? ? i, openOutputs.valueAt(i)->isDuplicated(),
? ? ? ? ? ? ? ? openOutputs.valueAt(i)->supportedDevices().toString().c_str());
? ? ? ? if (openOutputs.valueAt(i)->supportsAllDevices(devices)
? ? ? ? ? ? ? ? && openOutputs.valueAt(i)->devicesSupportEncodedFormats(devices.types())) {
? ? ? ? ? ? ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
? ? ? ? ? ? outputs.add(openOutputs.keyAt(i));
? ? ? ? }
? ? }
? ? return outputs;
}

selectOutput

根据flags, format, channel_mask从audio_io_handles 中找到bestMatched

audio_io_handle_t AudioPolicyManager::selectOutput(

???????????????????????????????????????????????????????const SortedVector<audio_io_handle_t>& outputs,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?audio_output_flags_t flags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?audio_format_t format,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?audio_channel_mask_t channelMask,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?uint32_t samplingRate)
{
? ? audio_io_handle_t primary_output = 0;
? ? bool isCts = getAppMaskByName(callingAppName) & APP_TYPE_CTS_AUDIOPRO ? true : false;

? ? LOG_ALWAYS_FATAL_IF(!(format == AUDIO_FORMAT_INVALID || audio_is_linear_pcm(format)),
? ? ? ? "%s called with format %#x", __func__, format);

? ? // Flags disqualifying an output: the match must happen before calling selectOutput()
? ? static const audio_output_flags_t kExcludedFlags = (audio_output_flags_t)
? ? ? ? (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);

? ? // Flags expressing a functional request: must be honored in priority over
? ? // other criteria
? ? static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t)
? ? ? ? (AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC |
? ? ? ? ? ? AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM | AUDIO_OUTPUT_FLAG_VIRTUAL_DEEP_BUFFER);
? ? // Flags expressing a performance request: have lower priority than serving
? ? // requested sampling rate or channel mask
? ? static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t)
? ? ? ? (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER |
? ? ? ? ? ? AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_SYNC);

? ? const audio_output_flags_t functionalFlags =
? ? ? ? (audio_output_flags_t)(flags & kFunctionalFlags);
? ? const audio_output_flags_t performanceFlags =
? ? ? ? (audio_output_flags_t)(flags & kPerformanceFlags);

? ? audio_io_handle_t bestOutput = (outputs.size() == 0) ? AUDIO_IO_HANDLE_NONE : outputs[0];

? ? // select one output among several that provide a path to a particular device or set of
? ? // devices (the list was previously build by getOutputsForDevices()).
? ? // The priority is as follows:
? ? // 1: the output supporting haptic playback when requesting haptic playback
? ? // 2: the output with the highest number of requested functional flags
? ? // 3: the output supporting the exact channel mask
? ? // 4: the output with a higher channel count than requested
? ? // 5: the output with a higher sampling rate than requested
? ? // 6: the output with the highest number of requested performance flags
? ? // 7: the output with the bit depth the closest to the requested one
? ? // 8: the primary output
? ? // 9: the first output in the list

? ? // matching criteria values in priority order for best matching output so far
? ? std::vector<uint32_t> bestMatchCriteria(8, 0);

? ? const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
? ? const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(
? ? ? ? channelMask & AUDIO_CHANNEL_HAPTIC_ALL);

? ? for (audio_io_handle_t output : outputs) {
? ? ? ? sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
? ? ? ? // matching criteria values in priority order for current output
? ? ? ? std::vector<uint32_t> currentMatchCriteria(8, 0);

? ? ? ? if (outputDesc->isDuplicated()) {
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? if ((kExcludedFlags & outputDesc->mFlags) != 0) {
? ? ? ? ? ? continue;
? ? ? ? }

? ? ? ? // If haptic channel is specified, use the haptic output if present.
? ? ? ? // When using haptic output, same audio format and sample rate are required.
? ? ? ? const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
? ? ? ? ? ? outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
? ? ? ? if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
? ? ? ? ? ? continue;
? ? ? ? }
? ? ? ? if (outputHapticChannelCount >= hapticChannelCount
? ? ? ? ? ? && format == outputDesc->getFormat()
? ? ? ? ? ? && samplingRate == outputDesc->getSamplingRate()) {
? ? ? ? ? ? ? ? currentMatchCriteria[0] = outputHapticChannelCount;
? ? ? ? }

? ? ? ? // functional flags match
? ? ? ? currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);

? ? ? ? // channel mask and channel count match
? ? ? ? uint32_t outputChannelCount = audio_channel_count_from_out_mask(
? ? ? ? ? ? ? ? outputDesc->getChannelMask());
? ? ? ? if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
? ? ? ? ? ? channelCount <= outputChannelCount) {
? ? ? ? ? ? if ((audio_channel_mask_get_representation(channelMask) ==
? ? ? ? ? ? ? ? ? ? audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
? ? ? ? ? ? ? ? ? ? ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
? ? ? ? ? ? ? ? currentMatchCriteria[2] = outputChannelCount;
? ? ? ? ? ? }
? ? ? ? ? ? currentMatchCriteria[3] = outputChannelCount;
? ? ? ? }

? ? ? ? // sampling rate match
? ? ? ? if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
? ? ? ? ? ? ? ? samplingRate <= outputDesc->getSamplingRate()) {
? ? ? ? ? ? currentMatchCriteria[4] = outputDesc->getSamplingRate();
? ? ? ? }

? ? ? ? // performance flags match
? ? ? ? currentMatchCriteria[5] = popcount(outputDesc->mFlags & performanceFlags);

? ? ? ? // format match
? ? ? ? if (format != AUDIO_FORMAT_INVALID) {
? ? ? ? ? ? currentMatchCriteria[6] =
? ? ? ? ? ? ? ? PolicyAudioPort::kFormatDistanceMax -
? ? ? ? ? ? ? ? PolicyAudioPort::formatDistance(format, outputDesc->getFormat());
? ? ? ? }

? ? ? ? // primary output match
? ? ? ? currentMatchCriteria[7] = outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY;
? ? ? ? if (currentMatchCriteria[7])
? ? ? ? ? ? primary_output = output;

? ? ? ? // compare match criteria by priority then value
? ? ? ? if (std::lexicographical_compare(bestMatchCriteria.begin(), bestMatchCriteria.end(),
? ? ? ? ? ? ? ? currentMatchCriteria.begin(), currentMatchCriteria.end())) {
? ? ? ? ? ? bestMatchCriteria = currentMatchCriteria;
? ? ? ? ? ? bestOutput = output;

? ? ? ? ? ? std::stringstream result;
? ? ? ? ? ? std::copy(bestMatchCriteria.begin(), bestMatchCriteria.end(),
? ? ? ? ? ? ? ? std::ostream_iterator<int>(result, " "));
? ? ? ? ? ? ALOGV("%s new bestOutput %d criteria %s",
? ? ? ? ? ? ? ? __func__, bestOutput, result.str().c_str());
? ? ? ? }
? ? }

? ? {
? ? ? ? //only cts use ull, the others use primary output
? ? ? ? //if do not have ull profile(audio_policy_configuration.xml), cannot create ull desc.
? ? ? ? //so it must create ull output first
? ? ? ? sp<SwAudioOutputDescriptor> outputDescPrimary = mOutputs.valueFor(bestOutput);
? ? ? ? if (outputDescPrimary != nullptr && (outputDescPrimary->mFlags == (AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW))
? ? ? ? ? ? ? ? ? ? ?&& !isCts && primary_output != 0) {
? ? ? ? ? ? bestOutput = primary_output;
? ? ? ? }
? ? }

? ? return bestOutput;
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:58:42  更:2021-08-27 12:01:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:41:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码