一、CarDucking介绍
CarDucking用来处理声音的淡入和淡出,在CarAudioFocus处理中会被调用。
二、CarDucking相关类
CarDucking
CarDucking代码位于:
packages/services/Car/service/src/com/android/car/audio/CarDucking.java
CarDucking的定义:
final class CarDucking implements CarFocusCallback {}
CarDuckingInfo
Ducking information for a given car audio zone based on its focus state.
CarDuckingInfo代码位于:
packages/services/Car/service/src/com/android/car/audio/CarDuckingInfo.java
CarDuckingInfo的定义:
public final class CarDuckingInfo {}
CarDuckingUtils
CarDuckingUtils代码位于:
packages/services/Car/service/src/com/android/car/audio/CarDuckingUtils.java
CarDuckingUtils的定义:
final class CarDuckingUtils {}
三、CarDucking流程分析
CarDucking创建流程分析
在CarAudioService的init方法中会调用setupDynamicRoutingLocked,在setupDynamicRoutingLocked中会创建CarDucking对象:
//packages/services/Car/service/src/com/android/car/audio/CarAudioService.java
public class CarAudioService extends ICarAudio.Stub implements CarServiceBase {
private CarZonesAudioFocus mFocusHandler;
private void setupDynamicRoutingLocked() {
final AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
builder.setLooper(Looper.getMainLooper());
loadCarAudioZonesLocked(); //加载CarAudioZones
for (int i = 0; i < mCarAudioZones.size(); i++) {
CarAudioZone zone = mCarAudioZones.valueAt(i);
// Ensure HAL gets our initial value
// 确保 HAL 获得我们的初始值
zone.synchronizeCurrentGainIndex();
Slogf.v(TAG, "Processed audio zone: %s", zone);
}
CarAudioDynamicRouting.setupAudioDynamicRouting(builder, mCarAudioZones); //设置动态路由
// Attach the {@link AudioPolicyVolumeCallback}
CarAudioPolicyVolumeCallback
.addVolumeCallbackToPolicy(builder, this, mAudioManager,
mUseCarVolumeGroupMuting);
AudioControlWrapper audioControlWrapper = getAudioControlWrapperLocked();
if (mUseHalDuckingSignals) { //如果使用HalDuckingSignals
if (audioControlWrapper.supportsFeature(AUDIOCONTROL_FEATURE_AUDIO_DUCKING)) { //如果支持DUCKING功能
mCarDucking = new CarDucking(mCarAudioZones, audioControlWrapper);//创建CarDucking对象
}
}
if (mUseCarVolumeGroupMuting) { //如果支持CarVolumeGroupMuting
mCarVolumeGroupMuting = new CarVolumeGroupMuting(mCarAudioZones, audioControlWrapper); //创建CarVolumeGroupMuting对象
}
// Configure our AudioPolicy to handle focus events.
// This gives us the ability to decide which audio focus requests to accept and bypasses
// the framework ducking logic.
// 配置我们的音频策略以处理焦点事件。这使我们能够决定接受哪些音频焦点请求并绕过框架闪避逻辑。
mFocusHandler = CarZonesAudioFocus.createCarZonesAudioFocus(mAudioManager,
mContext.getPackageManager(),
mCarAudioZones,
mCarAudioSettings,
mCarDucking); //创建CarZonesAudioFocus
builder.setAudioPolicyFocusListener(mFocusHandler); //设置AudioPolicy的音频焦点侦听器
builder.setIsAudioFocusPolicy(true);
mAudioPolicy = builder.build();
// Connect the AudioPolicy and the focus listener
// 连接音频策略和焦点侦听器
mFocusHandler.setOwningPolicy(this, mAudioPolicy);
int r = mAudioManager.registerAudioPolicy(mAudioPolicy);
if (r != AudioManager.SUCCESS) {
throw new RuntimeException("registerAudioPolicy failed " + r);
}
setupOccupantZoneInfo();
}
}
CarDucking的构造方法如下:
//packages/services/Car/service/src/com/android/car/audio/CarDucking.java
final class CarDucking implements CarFocusCallback {
private final SparseArray<CarDuckingInfo> mCurrentDuckingInfo = new SparseArray<>();
CarDucking(@NonNull SparseArray<CarAudioZone> carAudioZones,
@NonNull AudioControlWrapper audioControlWrapper) {
mCarAudioZones = Objects.requireNonNull(carAudioZones);
mAudioControlWrapper = Objects.requireNonNull(audioControlWrapper);
for (int i = 0; i < carAudioZones.size(); i++) {
int zoneId = carAudioZones.keyAt(i);
mCurrentDuckingInfo.put(
zoneId,
new CarDuckingInfo(
zoneId, new ArrayList<>(), new ArrayList<>(), new ArrayList<>())); //创建CarDuckingInfo对象,并将CarDuckingInfo对象放入mCurrentDuckingInfo中
}
}
}
CarDuckingInfo的构造方法如下:
//packages/services/Car/service/src/com/android/car/audio/CarDuckingInfo.java
public final class CarDuckingInfo {
public CarDuckingInfo(
int zoneId,
@NonNull List<String> addressesToDuck,
@NonNull List<String> addressesToUnduck,
@NonNull List<PlaybackTrackMetadata> playbackMetaDataHoldingFocus) {
mZoneId = zoneId;
mAddressesToDuck = Objects.requireNonNull(addressesToDuck);
mAddressesToUnduck = Objects.requireNonNull(addressesToUnduck);
mPlaybackMetaDataHoldingFocus = Objects.requireNonNull(playbackMetaDataHoldingFocus);
}
}