这个流程比较长,我们分段理解和分析,首先是从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了,在这里就不再分析了。