Android13 CarAudioManager setGroupVolume流程分析

这个流程比较长,我们分段理解和分析,首先是从CarAudioManager到IAudioPolicyService,这个阶段的流程图如下:

首先是CarAudioManager.java的setGroupVolume方法:

//packages/services/Car/car-lib/src/android/car/media/CarAudioManager.java
    @SystemApi
    @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
    public void setGroupVolume(int zoneId, int groupId, int index, int flags) {
        try {
            mService.setGroupVolume(zoneId, groupId, index, flags);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

调用了mService.setGroupVolume方法,mService的定义为“private final ICarAudio mService;”,ICarAudio为aidl接口,定义如下:

//packages/services/Car/car-lib/src/android/car/media/ICarAudio.aidl
interface ICarAudio {
    ......
    void setGroupVolume(int zoneId, int groupId, int index, int flags);
    ......
}

而CarAudioService继承了ICarAudio.Stub接口:

//packages/services/Car/service/src/com/android/car/audioCarAudioService.java
public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
    @Override
    public void setGroupVolume(int zoneId, int groupId, int index, int flags) {
        enforcePermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME);
        callbackGroupVolumeChange(zoneId, groupId, flags); //调用callbackGroupVolumeChange
        // For legacy stream type based volume control
        if (!mUseDynamicRouting) { //如果不支持动态路由,直接调用AudioManager的setStreamVolume
            mAudioManager.setStreamVolume(
                    CarAudioDynamicRouting.STREAM_TYPES[groupId], index, flags);
            return;
        }
        synchronized (mImplLock) {
     //此处可以追加判断,如果不是副屏的BT音量就调用getAudioControlWrapperLocked().setGroupVolume(zoneId,groupId);
            CarVolumeGroup group = getCarVolumeGroupLocked(zoneId, groupId); //取得Volume Group
            group.setCurrentGainIndex(index); //设置Group Volume
        }
    }
}

上面方法主要处理如下:

调用callbackGroupVolumeChange

调用getCarVolumeGroupLocked取得VolumeGroup

调用CarVolumeGroup的setCurrentGainIndex设置Group Volume

下面我们分别分析:

callbackGroupVolumeChange

首先是callbackGroupVolumeChange方法:

//packages/services/Car/service/src/com/android/car/audioCarAudioService.java
public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
    private final CarVolumeCallbackHandler mCarVolumeCallbackHandler;
    private void callbackGroupVolumeChange(int zoneId, int groupId, int flags) {
        if (mUseDynamicRouting && !isPlaybackOnVolumeGroupActive(zoneId, groupId)) {
            flags |= FLAG_PLAY_SOUND;
        }
        mCarVolumeCallbackHandler.onVolumeGroupChange(zoneId, groupId, flags); //调用CarVolumeCallbackHandler的onVolumeGroupChange方法
    }
}

CarVolumeCallbackHandler用于管理汽车Volume变化的回调,处理onVolumeGroupChange外还有onMasterMuteChanged和onGroupMuteChange

调用CarVolumeCallbackHandler的onVolumeGroupChange方法:

//packages/services/Car/service/src/com/android/car/audio/CarVolumeCallbackHandler.java
class CarVolumeCallbackHandler {
    void onVolumeGroupChange(int zoneId, int groupId, int flags) {
        for (BinderInterfaceContainer.BinderInterface<ICarVolumeCallback> callback :
                mVolumeCallbackContainer.getInterfaces()) {
            try {
                callback.binderInterface.onGroupVolumeChanged(zoneId, groupId, flags); 调用onGroupVolumeChanged回调
            } catch (RemoteException e) {
                Slogf.e(CarLog.TAG_AUDIO, "Failed to callback onGroupVolumeChanged", e);
            }
        }
    }
}

调用onGroupVolumeChanged回调:

//packages/services/Car/car-lib/src/android/car/media/CarAudioManager.java
public final class CarAudioManager extends CarManagerBase {
    private final EventHandler mEventHandler;
    private final ICarVolumeCallback mCarVolumeCallbackImpl =
            new android.car.media.ICarVolumeCallback.Stub() {
        @Override
        public void onGroupVolumeChanged(int zoneId, int groupId, int flags) {
            mEventHandler.dispatchOnGroupVolumeChanged(zoneId, groupId, flags); //调用EventHandler的dispatchOnGroupVolumeChanged方法
        }
    }
}

调用EventHandler的dispatchOnGroupVolumeChanged方法:

//packages/services/Car/car-lib/src/android/car/media/CarAudioManager.java
public final class CarAudioManager extends CarManagerBase {
    private final class EventHandler extends Handler {
        private void dispatchOnGroupVolumeChanged(int zoneId, int groupId, int flags) {
            VolumeGroupChangeInfo volumeInfo = new VolumeGroupChangeInfo(zoneId, groupId, flags);
            sendMessage(obtainMessage(MSG_GROUP_VOLUME_CHANGE, volumeInfo)); //发送MSG_GROUP_VOLUME_CHANGE消息
        }
    }
}

发送的MSG_GROUP_VOLUME_CHANGE消息会在EventHandler中处理:

//packages/services/Car/car-lib/src/android/car/media/CarAudioManager.java
public final class CarAudioManager extends CarManagerBase {
    private final class EventHandler extends Handler {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GROUP_VOLUME_CHANGE:
                    VolumeGroupChangeInfo volumeInfo = (VolumeGroupChangeInfo) msg.obj;
                    handleOnGroupVolumeChanged(volumeInfo.mZoneId, volumeInfo.mGroupId,
                            volumeInfo.mFlags);
                    break;
            }
        }
    }
}

调用handleOnGroupVolumeChanged方法:

//packages/services/Car/car-lib/src/android/car/media/CarAudioManager.java
public final class CarAudioManager extends CarManagerBase {
    private void handleOnGroupVolumeChanged(int zoneId, int groupId, int flags) {
        for (CarVolumeCallback callback : mCarVolumeCallbacks) {
            callback.onGroupVolumeChanged(zoneId, groupId, flags); //调用CarVolumeCallback的onGroupMuteChanged方法
        }
    }
}

getCarVolumeGroupLocked

再分析getCarVolumeGroupLocked方法,这个方法的作用是通过zoneId和groupId取得CarVolumeGroup的实例:

//packages/services/Car/service/src/com/android/car/audioCarAudioService.java
public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
    private CarVolumeGroup getCarVolumeGroupLocked(int zoneId, int groupId) {
        return getCarAudioZoneLocked(zoneId).getVolumeGroup(groupId); //调用getCarAudioZoneLocked方法取得CarAudioZone,再通过CarAudioZone的getVolumeGroup取得CarVolumeGroup 
    }
}

调用getCarAudioZoneLocked方法取得CarAudioZone:

//packages/services/Car/service/src/com/android/car/audioCarAudioService.java
public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
    private CarAudioZone getCarAudioZoneLocked(int zoneId) {
        checkAudioZoneIdLocked(zoneId);
        return mCarAudioZones.get(zoneId);
    }
}

通过CarAudioZone的getVolumeGroup取得CarVolumeGroup:

//packages/services/Car/service/src/com/android/car/audio/CarAudioZone.java
class CarAudioZone {
    CarVolumeGroup getVolumeGroup(int groupId) {
        Preconditions.checkArgumentInRange(groupId, 0, mVolumeGroups.size() - 1,
                "groupId(" + groupId + ") is out of range");
        return mVolumeGroups.get(groupId);
    }
}

setCurrentGainIndex

最后是CarVolumeGroup的setCurrentGainIndex方法:

//packages/services/Car/service/src/com/android/car/CarVolumeGroup.java
final class CarVolumeGroup {
    private final CarAudioSettings mSettingsManager;
    ......
    void setCurrentGainIndex(int gainIndex) {
        Preconditions.checkArgument(isValidGainIndex(gainIndex),
                "Gain out of range (%d:%d) index %d", mMinGain, mMaxGain, gainIndex);
        synchronized (mLock) {
            if (mIsMuted) {
                setMuteLocked(false);
            }
            setCurrentGainIndexLocked(gainIndex);
        }
    }
    ......
    private void setCurrentGainIndexLocked(int gainIndex) {
        int gainInMillibels = getGainForIndex(gainIndex);
        for (String address : mAddressToCarAudioDeviceInfo.keySet()) {
            CarAudioDeviceInfo info = mAddressToCarAudioDeviceInfo.get(address);
            info.setCurrentGain(gainInMillibels); //设置当前Gain值
        }


        mCurrentGainIndex = gainIndex;


        storeGainIndexForUserLocked(mCurrentGainIndex, mUserId); //存储用户Volume值
    }
    ......
    private void storeGainIndexForUserLocked(int gainIndex, @UserIdInt int userId) {
        mSettingsManager.storeVolumeGainIndexForUser(userId,
                mZoneId, mId, gainIndex); //存储用户Volume值
    }
    ......
}

CarVolumeGroup的setCurrentGainIndex方法然后中调用setCurrentGainIndexLocked,在setCurrentGainIndexLocked中又调用了CarAudioDeviceInfo的storeVolumeGainIndexForUser方法:

//packages/services/Car/service/src/com/android/car/CarAudioDeviceInfo.java
class CarAudioDeviceInfo {
    ......
   // Input is in millibels
    void setCurrentGain(int gainInMillibels) {
        // Clamp the incoming value to our valid range.  Out of range values ARE legal input
        //判断Gain值是否超过最小和最大范围,如果超过就用最大和最小值
        if (gainInMillibels < mMinGain) {
            gainInMillibels = mMinGain;
        } else if (gainInMillibels > mMaxGain) {
            gainInMillibels = mMaxGain;
        }


        if (AudioManagerHelper.setAudioDeviceGain(mAudioManager,
                getAddress(), gainInMillibels, true)) { //设置Audio设备的Volume Gain值
            // Since we can't query for the gain on a device port later,
            // we have to remember what we asked for
            mCurrentGain = gainInMillibels;
        } else {
            Slogf.e(CarLog.TAG_AUDIO, "Failed to setAudioPortGain " + gainInMillibels
                    + " for output device " + getAddress());
        }
    }
    ......
}

CarAudioDeviceInfo的setCurrentGain方法中调用AudioManagerHelper的setAudioDeviceGain方法:

//packages/services/Car/car-builtin-lib/src/android/car/builtin/media/AudioManagerHelper.Java
public final class AudioManagerHelper {
    public static boolean setAudioDeviceGain(@NonNull AudioManager audioManager,
            @NonNull String address, int gainInMillibels, boolean isOutput) {
        Preconditions.checkNotNull(audioManager,
                "Audio Manager can not be null in set device gain, device address %s", address);
        AudioDeviceInfo deviceInfo = getAudioDeviceInfo(audioManager, address, isOutput); //获取Audio设备信息


        AudioGain audioGain = getAudioGain(deviceInfo.getPort());//获取Audio Gain值


        // size of gain values is 1 in MODE_JOINT
 //为此增益控制器构建有效的增益配置
        AudioGainConfig audioGainConfig = audioGain.buildConfig( 
                AudioGain.MODE_JOINT,
                audioGain.channelMask(),
                new int[] { gainInMillibels },
                0);
        if (audioGainConfig == null) {
            throw new IllegalStateException("Failed to construct AudioGainConfig for device "
                    + address);
        }


        int r = AudioManager.setAudioPortGain(deviceInfo.getPort(), audioGainConfig);//调用AudioManager的setAudioPortGain方法
        if (r == AudioManager.SUCCESS) {
            return true;
        }
        return false;
    }
}

调用AudioManager的setAudioPortGain方法:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
        if (port == null || gain == null) {
            return ERROR_BAD_VALUE;
        }
        AudioPortConfig activeConfig = port.activeConfig();
        AudioPortConfig config = new AudioPortConfig(port, activeConfig.samplingRate(),
                                        activeConfig.channelMask(), activeConfig.format(), gain); //创建AudioPortConfig对象
        config.mConfigMask = AudioPortConfig.GAIN;
        return AudioSystem.setAudioPortConfig(config); //调用AudioSystem的SetAudioPortConfig,并返回处理结果
    }
}

调用AudioSystem的setAudioPortConfig,会转到AudioSystem的setAudioPortConfig函数:

//frameworks/av/media/libaudioclient/AudioSystem.cpp
status_t AudioSystem::setAudioPortConfig(const struct audio_port_config* config) {
    if (config == nullptr) {
        return BAD_VALUE;
    }


    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); //获取AudioPolicyService的引用
    if (aps == 0) return PERMISSION_DENIED;


    media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_port_config_AudioPortConfig(*config));
    return statusTFromBinderStatus(aps->setAudioPortConfig(configAidl)); 然后通过IAudioPolicyService.aidl,调用AudioPolicyService的setAudioPortConfig函数
}

IAudioPolicyService.aidl的setAudioPortConfig函数:

//frameworks/av/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
interface IAudioPolicyService {
    ......
    /** Set audio port configuration. */
    void setAudioPortConfig(in AudioPortConfig config);
    ......
}

到处这部分的时序就介绍完了,接下来介绍从IAudioPolicyService到AudioCommandThread的时序:

调用AudioPolicyService的setAudioPortConfig函数:

//frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfig& configAidl)
{
    audio_port_config config = VALUE_OR_RETURN_BINDER_STATUS(
            aidl2legacy_AudioPortConfig_audio_port_config(configAidl));
    RETURN_IF_BINDER_ERROR(
            binderStatusFromStatusT(AudioValidator::validateAudioPortConfig(config)));


    Mutex::Autolock _l(mLock);
    if(!modifyAudioRoutingAllowed()) {
        return binderStatusFromStatusT(PERMISSION_DENIED);
    }
    if (mAudioPolicyManager == NULL) {
        return binderStatusFromStatusT(NO_INIT);
    }
    AutoCallerClear acc;
    return binderStatusFromStatusT(mAudioPolicyManager->setAudioPortConfig(&config)); //调用AudioPolicyManager的setAudioPortConfig函数
}

调用AudioPolicyManager的setAudioPortConfig方法:

//frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
status_t AudioPolicyManager::setAudioPortConfig(const struct audio_port_config *config)
{
    ALOGV("setAudioPortConfig()");


    if (config == NULL) {
        return BAD_VALUE;
    }
    ALOGV("setAudioPortConfig() on port handle %d", config->id);
    // Only support gain configuration for now
    if (config->config_mask != AUDIO_PORT_CONFIG_GAIN) {
        return INVALID_OPERATION;
    }


    sp<AudioPortConfig> audioPortConfig;
    if (config->type == AUDIO_PORT_TYPE_MIX) {
        if (config->role == AUDIO_PORT_ROLE_SOURCE) {
            sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputFromId(config->id);
            if (outputDesc == NULL) {
                return BAD_VALUE;
            }
            ALOG_ASSERT(!outputDesc->isDuplicated(),
                        "setAudioPortConfig() called on duplicated output %d",
                        outputDesc->mIoHandle);
            audioPortConfig = outputDesc;
        } else if (config->role == AUDIO_PORT_ROLE_SINK) {
            sp<AudioInputDescriptor> inputDesc = mInputs.getInputFromId(config->id);
            if (inputDesc == NULL) {
                return BAD_VALUE;
            }
            audioPortConfig = inputDesc;
        } else {
            return BAD_VALUE;
        }
    } else if (config->type == AUDIO_PORT_TYPE_DEVICE) {
        sp<DeviceDescriptor> deviceDesc;
        if (config->role == AUDIO_PORT_ROLE_SOURCE) {
            deviceDesc = mAvailableInputDevices.getDeviceFromId(config->id);
        } else if (config->role == AUDIO_PORT_ROLE_SINK) {
            deviceDesc = mAvailableOutputDevices.getDeviceFromId(config->id);
        } else {
            return BAD_VALUE;
        }
        if (deviceDesc == NULL) {
            return BAD_VALUE;
        }
        audioPortConfig = deviceDesc;
    } else {
        return BAD_VALUE;
    }


    struct audio_port_config backupConfig = {};
    status_t status = audioPortConfig->applyAudioPortConfig(config, &backupConfig);
    if (status == NO_ERROR) {
        struct audio_port_config newConfig = {};
        audioPortConfig->toAudioPortConfig(&newConfig, config);
        status = mpClientInterface->setAudioPortConfig(&newConfig, 0);
    }
    if (status != NO_ERROR) {
        audioPortConfig->applyAudioPortConfig(&backupConfig);
    }


    return status;
}

调用AudioPolicyClient的setAudioPortConfig函数:

//frameworks/av/services/audiopolicy/service/AudioPolicyClientImpl.cpp
status_t AudioPolicyService::AudioPolicyClient::setAudioPortConfig(
                                                        const struct audio_port_config *config,
                                                        int delayMs)
{
    return mAudioPolicyService->clientSetAudioPortConfig(config, delayMs);
}

调用AudioPolicyService的clientSetAudioPortConfig函数:

//frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config,
                                                      int delayMs)
{
    return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}

调用AudioCommandThread的setAudioPortConfigCommand函数:

//frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
                                            const struct audio_port_config *config, int delayMs)
{
    sp<AudioCommand> command = new AudioCommand();
    command->mCommand = SET_AUDIOPORT_CONFIG;
    SetAudioPortConfigData *data = new SetAudioPortConfigData();
    data->mConfig = *config;
    command->mParam = data;
    command->mWaitStatus = true;
    ALOGV("AudioCommandThread() adding set port config delay %d", delayMs);
    return sendCommand(command, delayMs); //发送SET_AUDIOPORT_CONFIG消息给AudioCommandThread
}

在AudioCommandThread的threadLoop函数处理消息:

//frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
bool AudioPolicyService::AudioCommandThread::threadLoop()
{
......
                case SET_AUDIOPORT_CONFIG: {
                    SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
                    ALOGV("AudioCommandThread() processing set port config");
                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
                    if (af == 0) {
                        command->mStatus = PERMISSION_DENIED;
                    } else {
                        mLock.unlock();
                        command->mStatus = af->setAudioPortConfig(&data->mConfig); 通过IAudioFlinger调用AudioFlinger的setAudioPortConfig函数
                        mLock.lock();
                    }
                    } break;
......
}

到这里上面的时序就介绍完了,下面介绍从IAudioFlinger到AudioHAL的流程:

 IAudioFlinger的setAudioPortConfig函数:

//frameworks/av/media/libaudioclient/IAudioFlinger.cpp
class AudioFlingerClientAdapter : public IAudioFlinger {}


//frameworks/av/media/libaudioclient/IAudioFlinger.cpp
AudioFlingerClientAdapter::AudioFlingerClientAdapter(
        const sp<media::IAudioFlingerService> delegate) : mDelegate(delegate) {}


const sp<media::IAudioFlingerService> mDelegate;
status_t AudioFlingerClientAdapter::setAudioPortConfig(const struct audio_port_config* config) {
    media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
            legacy2aidl_audio_port_config_AudioPortConfig(*config));
    return statusTFromBinderStatus(mDelegate->setAudioPortConfig(configAidl)); 调用IAudioFlingerService的setAudioPortConfig
}

IAudioFlingerService的定义如下:

//frameworks/av/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
interface IAudioFlingerService {
    .......
    /* Set audio port configuration */
    void setAudioPortConfig(in AudioPortConfig config);
    ......
}

调用AudioFlinger的setAudioPortConfig函数:

//frameworks/av/services/AudioFlinger.cpp
status_t AudioFlinger::setAudioPortConfig(const struct audio_port_config *config)
{
    ALOGV(__func__);


    status_t status = AudioValidator::validateAudioPortConfig(*config);
    if (status != NO_ERROR) {
        return status;
    }


    audio_module_handle_t module;
    if (config->type == AUDIO_PORT_TYPE_DEVICE) {
        module = config->ext.device.hw_module;
    } else {
        module = config->ext.mix.hw_module;
    }


    Mutex::Autolock _l(mLock);
    AutoMutex lock(mHardwareLock);
    ssize_t index = mAudioHwDevs.indexOfKey(module);
    if (index < 0) {
        ALOGW("%s() bad hw module %d", __func__, module);
        return BAD_VALUE;
    }


    AudioHwDevice *audioHwDevice = mAudioHwDevs.valueAt(index);
    return audioHwDevice->hwDevice()->setAudioPortConfig(config);
}

调用DeviceHalInterface的setAudioPortConfig方法,DeviceHalInterface是一个接口由DeviceHalHidl实现,因此会调用DeviceHalHidl的setAudioPortConfig:

DeviceHalHidl.cpp
sp<::android::hardware::audio::CPP_VERSION::IDevice> mDevice;
status_t DeviceHalHidl::setAudioPortConfig(const struct audio_port_config *config) {
    TIME_CHECK();
    if (mDevice == 0) return NO_INIT;
    AudioPortConfig hidlConfig;
    HidlUtils::audioPortConfigFromHal(*config, &hidlConfig);
    return processReturn("setAudioPortConfig", mDevice->setAudioPortConfig(hidlConfig)); 调用AudioHal的setAudioPortConfig
}

到这里就调用到AudioHal了,在这里就不再分析了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值