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.util.SparseArray;
19 
20 import com.android.car.audio.CarAudioContext.AudioContext;
21 import com.android.internal.annotations.VisibleForTesting;
22 import com.android.internal.util.Preconditions;
23 
24 import java.util.List;
25 import java.util.Objects;
26 
27 final class CarVolumeGroupFactory {
28     private static final int UNSET_STEP_SIZE = -1;
29 
30     private final String mName;
31     private final int mId;
32     private final int mZoneId;
33     private final int mConfigId;
34     private final boolean mUseCarVolumeGroupMute;
35     private final CarAudioSettings mCarAudioSettings;
36     private final SparseArray<CarAudioDeviceInfo> mContextToDeviceInfo = new SparseArray<>();
37     private final CarAudioContext mCarAudioContext;
38     private final AudioManagerWrapper mAudioManager;
39     private final CarActivationVolumeConfig mCarActivationVolumeConfig;
40 
41     private int mStepSize = UNSET_STEP_SIZE;
42     private int mDefaultGain = Integer.MIN_VALUE;
43     private int mMaxGain = Integer.MIN_VALUE;
44     private int mMinGain = Integer.MAX_VALUE;
45 
CarVolumeGroupFactory(AudioManagerWrapper audioManager, CarAudioSettings carAudioSettings, CarAudioContext carAudioContext, int zoneId, int configId, int volumeGroupId, String name, boolean useCarVolumeGroupMute, CarActivationVolumeConfig carActivationVolumeConfig)46     CarVolumeGroupFactory(AudioManagerWrapper audioManager, CarAudioSettings carAudioSettings,
47             CarAudioContext carAudioContext, int zoneId, int configId, int volumeGroupId,
48             String name, boolean useCarVolumeGroupMute,
49             CarActivationVolumeConfig carActivationVolumeConfig) {
50         mAudioManager = audioManager;
51         mCarAudioSettings = Objects.requireNonNull(carAudioSettings,
52                 "Car audio settings can not be null");
53         mCarAudioContext = Objects.requireNonNull(carAudioContext,
54                 "Car audio context can not be null");
55         mZoneId = zoneId;
56         mConfigId = configId;
57         mId = volumeGroupId;
58         mName = Objects.requireNonNull(name, "Car Volume Group name can not be null");
59         mUseCarVolumeGroupMute = useCarVolumeGroupMute;
60         mCarActivationVolumeConfig = Objects.requireNonNull(carActivationVolumeConfig,
61                 "Car activation volume config can not be null");
62     }
63 
getCarVolumeGroup(boolean useCoreAudioVolume)64     CarVolumeGroup getCarVolumeGroup(boolean useCoreAudioVolume) {
65         Preconditions.checkArgument(mContextToDeviceInfo.size() != 0,
66                 "setDeviceInfoForContext has to be called at least once before building");
67         CarVolumeGroup group;
68         if (useCoreAudioVolume) {
69             group = new CoreAudioVolumeGroup(mAudioManager, mCarAudioContext, mCarAudioSettings,
70                     mContextToDeviceInfo, mZoneId, mConfigId, mId, mName, mUseCarVolumeGroupMute,
71                     mCarActivationVolumeConfig);
72         } else {
73             group = new CarAudioVolumeGroup(mCarAudioContext, mCarAudioSettings,
74                     mContextToDeviceInfo, mZoneId, mConfigId, mId, mName, mStepSize, mDefaultGain,
75                     mMinGain, mMaxGain, mUseCarVolumeGroupMute, mCarActivationVolumeConfig);
76         }
77         group.init();
78         return group;
79     }
80 
setDeviceInfoForContext(int carAudioContextId, CarAudioDeviceInfo info)81     void setDeviceInfoForContext(int carAudioContextId, CarAudioDeviceInfo info) {
82         Preconditions.checkArgument(mContextToDeviceInfo.get(carAudioContextId) == null,
83                 "Context %s has already been set to %s",
84                 mCarAudioContext.toString(carAudioContextId),
85                 mContextToDeviceInfo.get(carAudioContextId));
86 
87         if (mContextToDeviceInfo.size() == 0) {
88             mStepSize = info.getStepValue();
89         } else {
90             Preconditions.checkArgument(
91                     info.getStepValue() == mStepSize,
92                     "Gain controls within one group must have same step value");
93         }
94 
95         mContextToDeviceInfo.put(carAudioContextId, info);
96 
97         // TODO(b/271749259) - this logic is redundant now. clean up
98         if (info.getDefaultGain() > mDefaultGain) {
99             // We're arbitrarily selecting the highest
100             // device default gain as the group's default.
101             mDefaultGain = info.getDefaultGain();
102         }
103         if (info.getMaxGain() > mMaxGain) {
104             mMaxGain = info.getMaxGain();
105         }
106         if (info.getMinGain() < mMinGain) {
107             mMinGain = info.getMinGain();
108         }
109     }
110 
setNonLegacyContexts(CarAudioDeviceInfo info)111     void setNonLegacyContexts(CarAudioDeviceInfo info) {
112         List<Integer> nonLegacyCarSystemContexts = CarAudioContext.getCarSystemContextIds();
113         for (int index = 0; index < nonLegacyCarSystemContexts.size(); index++) {
114             @AudioContext int audioContext = nonLegacyCarSystemContexts.get(index);
115             setDeviceInfoForContext(audioContext, info);
116         }
117     }
118 
119     @VisibleForTesting
getMinGain()120     int getMinGain() {
121         return mMinGain;
122     }
123 
124     @VisibleForTesting
getMaxGain()125     int getMaxGain() {
126         return mMaxGain;
127     }
128 
129     @VisibleForTesting
getDefaultGain()130     int getDefaultGain() {
131         return mDefaultGain;
132     }
133 }
134