• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.car.audio;
18 
19 import android.annotation.NonNull;
20 import android.car.builtin.util.Slogf;
21 import android.hardware.automotive.audiocontrol.Reasons;
22 import android.util.SparseArray;
23 
24 import com.android.car.CarLog;
25 import com.android.car.audio.hal.AudioControlWrapper;
26 import com.android.car.audio.hal.HalAudioGainCallback;
27 
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Objects;
31 
32 /**
33  * Provides audio gain callback registration helpers and implements AudioGain listener business
34  * logic.
35  */
36 /* package */ final class CarAudioGainMonitor {
37     @NonNull private final AudioControlWrapper mAudioControlWrapper;
38     @NonNull private final SparseArray<CarAudioZone> mCarAudioZones;
39 
CarAudioGainMonitor( AudioControlWrapper audioControlWrapper, SparseArray<CarAudioZone> carAudioZones)40     CarAudioGainMonitor(
41             AudioControlWrapper audioControlWrapper,
42             SparseArray<CarAudioZone> carAudioZones) {
43         mAudioControlWrapper =
44                 Objects.requireNonNull(
45                         audioControlWrapper, "Audio Control Wrapper can not be null");
46         mCarAudioZones = Objects.requireNonNull(carAudioZones, "Car Audio Zones can not be null");
47     }
48 
reset()49     public void reset() {
50         // TODO (b/224885748): handle specific logic on IAudioControl service died event
51     }
52 
53     /**
54      * Registers {@code HalAudioGainCallback} on {@code AudioControlWrapper} to receive HAL audio
55      * gain change notifications.
56      */
registerAudioGainListener(HalAudioGainCallback callback)57     public void registerAudioGainListener(HalAudioGainCallback callback) {
58         Objects.requireNonNull(callback, "Hal Audio Gain callback can not be null");
59         mAudioControlWrapper.registerAudioGainCallback(callback);
60     }
61 
62     /** Unregisters {@code HalAudioGainCallback} from {@code AudioControlWrapper}. */
unregisterAudioGainListener()63     public void unregisterAudioGainListener() {
64         mAudioControlWrapper.unregisterAudioGainCallback();
65     }
66 
67     /**
68      * Audio Gain event dispatcher. Implements the callback that triggered from {@link
69      * IAudioGainCallback#onAudioDeviceGainsChanged} with the list of reasons and the list of {@link
70      * CarAudioGainConfigInfo} involved. It is in charge of dispatching /delegating to the zone the
71      * {@link CarAudioGainConfigInfo} belongs the processing of the callback.
72      */
handleAudioDeviceGainsChanged(List<Integer> reasons, List<CarAudioGainConfigInfo> gains)73     void handleAudioDeviceGainsChanged(List<Integer> reasons, List<CarAudioGainConfigInfo> gains) {
74         // Delegate to CarAudioZone / CarVolumeGroup
75         // Group gains by Audio Zones first
76         SparseArray<List<CarAudioGainConfigInfo>> gainsByZones = new SparseArray<>();
77         for (int index = 0; index < gains.size(); index++) {
78             CarAudioGainConfigInfo gain = gains.get(index);
79             int zone = gain.getZoneId();
80             if (!gainsByZones.contains(zone)) {
81                 gainsByZones.put(zone, new ArrayList<>(1));
82             }
83             gainsByZones.get(zone).add(gain);
84         }
85         for (int i = 0; i < gainsByZones.size(); i++) {
86             int zoneId = gainsByZones.keyAt(i);
87             if (!mCarAudioZones.contains(zoneId)) {
88                 Slogf.e(
89                         CarLog.TAG_AUDIO,
90                         "onAudioDeviceGainsChanged reported change on invalid "
91                                 + "zone: %d, reasons=%s, gains=%s",
92                         zoneId,
93                         reasons,
94                         gains);
95                 continue;
96             }
97             CarAudioZone carAudioZone = mCarAudioZones.get(zoneId);
98             carAudioZone.onAudioGainChanged(reasons, gainsByZones.valueAt(i));
99         }
100     }
101 
shouldBlockVolumeRequest(List<Integer> reasons)102     static boolean shouldBlockVolumeRequest(List<Integer> reasons) {
103         return reasons.contains(Reasons.FORCED_MASTER_MUTE)
104                 || reasons.contains(Reasons.TCU_MUTE)
105                 || reasons.contains(Reasons.REMOTE_MUTE);
106     }
107 
shouldLimitVolume(List<Integer> reasons)108     static boolean shouldLimitVolume(List<Integer> reasons) {
109         return reasons.contains(Reasons.THERMAL_LIMITATION)
110                 || reasons.contains(Reasons.SUSPEND_EXIT_VOL_LIMITATION);
111     }
112 
shouldDuckGain(List<Integer> reasons)113     static boolean shouldDuckGain(List<Integer> reasons) {
114         return reasons.contains(Reasons.ADAS_DUCKING) || reasons.contains(Reasons.NAV_DUCKING);
115     }
116 }
117