1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.car.audio; 17 18 import android.media.AudioManager; 19 import android.util.ArrayMap; 20 import android.util.SparseArray; 21 22 import com.android.car.audio.CarAudioContext.AudioContext; 23 import com.android.internal.annotations.VisibleForTesting; 24 import com.android.internal.util.Preconditions; 25 26 import java.util.List; 27 import java.util.Objects; 28 29 final class CarVolumeGroupFactory { 30 private static final int UNSET_STEP_SIZE = -1; 31 32 private final String mName; 33 private final int mId; 34 private final int mZoneId; 35 private final int mConfigId; 36 private final boolean mUseCarVolumeGroupMute; 37 private final CarAudioSettings mCarAudioSettings; 38 private final SparseArray<String> mContextToAddress = new SparseArray<>(); 39 private final CarAudioContext mCarAudioContext; 40 private final AudioManager mAudioManager; 41 private final ArrayMap<String, CarAudioDeviceInfo> mAddressToCarAudioDeviceInfo = 42 new ArrayMap<>(); 43 44 private int mStepSize = UNSET_STEP_SIZE; 45 private int mDefaultGain = Integer.MIN_VALUE; 46 private int mMaxGain = Integer.MIN_VALUE; 47 private int mMinGain = Integer.MAX_VALUE; 48 CarVolumeGroupFactory(AudioManager audioManager, CarAudioSettings carAudioSettings, CarAudioContext carAudioContext, int zoneId, int configId, int volumeGroupId, String name, boolean useCarVolumeGroupMute)49 CarVolumeGroupFactory(AudioManager audioManager, CarAudioSettings carAudioSettings, 50 CarAudioContext carAudioContext, int zoneId, int configId, int volumeGroupId, 51 String name, boolean useCarVolumeGroupMute) { 52 mAudioManager = audioManager; 53 mCarAudioSettings = Objects.requireNonNull(carAudioSettings, 54 "Car audio settings can not be null"); 55 mCarAudioContext = Objects.requireNonNull(carAudioContext, 56 "Car audio context can not be null"); 57 mZoneId = zoneId; 58 mConfigId = configId; 59 mId = volumeGroupId; 60 mName = Objects.requireNonNull(name, "Car Volume Group name can not be null"); 61 mUseCarVolumeGroupMute = useCarVolumeGroupMute; 62 } 63 getCarVolumeGroup(boolean useCoreAudioVolume)64 CarVolumeGroup getCarVolumeGroup(boolean useCoreAudioVolume) { 65 Preconditions.checkArgument(mStepSize != UNSET_STEP_SIZE, 66 "setDeviceInfoForContext has to be called at least once before building"); 67 CarVolumeGroup group; 68 if (useCoreAudioVolume) { 69 group = new CoreAudioVolumeGroup(mAudioManager, 70 mCarAudioContext, mCarAudioSettings, mContextToAddress, 71 mAddressToCarAudioDeviceInfo, mZoneId, mConfigId, mId, mName, 72 mUseCarVolumeGroupMute); 73 } else { 74 group = new CarAudioVolumeGroup(mCarAudioContext, mCarAudioSettings, 75 mContextToAddress, mAddressToCarAudioDeviceInfo, mZoneId, mConfigId, mId, mName, 76 mStepSize, mDefaultGain, mMinGain, mMaxGain, mUseCarVolumeGroupMute); 77 } 78 group.init(); 79 return group; 80 } 81 setDeviceInfoForContext(int carAudioContextId, CarAudioDeviceInfo info)82 void setDeviceInfoForContext(int carAudioContextId, CarAudioDeviceInfo info) { 83 Preconditions.checkArgument(mContextToAddress.get(carAudioContextId) == null, 84 "Context %s has already been set to %s", 85 mCarAudioContext.toString(carAudioContextId), 86 mContextToAddress.get(carAudioContextId)); 87 88 if (mAddressToCarAudioDeviceInfo.isEmpty()) { 89 mStepSize = info.getStepValue(); 90 } else { 91 Preconditions.checkArgument( 92 info.getStepValue() == mStepSize, 93 "Gain controls within one group must have same step value"); 94 } 95 96 mAddressToCarAudioDeviceInfo.put(info.getAddress(), info); 97 mContextToAddress.put(carAudioContextId, info.getAddress()); 98 99 // TODO(b/271749259) - this logic is redundant now. clean up 100 if (info.getDefaultGain() > mDefaultGain) { 101 // We're arbitrarily selecting the highest 102 // device default gain as the group's default. 103 mDefaultGain = info.getDefaultGain(); 104 } 105 if (info.getMaxGain() > mMaxGain) { 106 mMaxGain = info.getMaxGain(); 107 } 108 if (info.getMinGain() < mMinGain) { 109 mMinGain = info.getMinGain(); 110 } 111 } 112 setNonLegacyContexts(CarAudioDeviceInfo info)113 void setNonLegacyContexts(CarAudioDeviceInfo info) { 114 List<Integer> nonLegacyCarSystemContexts = CarAudioContext.getCarSystemContextIds(); 115 for (int index = 0; index < nonLegacyCarSystemContexts.size(); index++) { 116 @AudioContext int audioContext = nonLegacyCarSystemContexts.get(index); 117 setDeviceInfoForContext(audioContext, info); 118 } 119 } 120 121 @VisibleForTesting getMinGain()122 int getMinGain() { 123 return mMinGain; 124 } 125 126 @VisibleForTesting getMaxGain()127 int getMaxGain() { 128 return mMaxGain; 129 } 130 131 @VisibleForTesting getDefaultGain()132 int getDefaultGain() { 133 return mDefaultGain; 134 } 135 } 136