1 /*
2  * Copyright (C) 2015 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 #define LOG_TAG "APM::Volumes"
18 //#define LOG_NDEBUG 0
19 
20 //#define VERY_VERBOSE_LOGGING
21 #ifdef VERY_VERBOSE_LOGGING
22 #define ALOGVV ALOGV
23 #else
24 #define ALOGVV(a...) do { } while(0)
25 #endif
26 
27 #include "StreamDescriptor.h"
28 #include "Gains.h"
29 #include "policy.h"
30 #include <utils/Log.h>
31 #include <utils/String8.h>
32 
33 namespace android {
34 
35 // --- StreamDescriptor class implementation
36 
StreamDescriptor()37 StreamDescriptor::StreamDescriptor()
38     :   mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
39 {
40     // Initialize the current stream's index to mIndexMax so volume isn't 0 in
41     // cases where the Java layer doesn't call into the audio policy service to
42     // set the default volume.
43     mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME, mIndexMax);
44 }
45 
getVolumeIndex(audio_devices_t device) const46 int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
47 {
48     device = Volume::getDeviceForVolume(device);
49     // there is always a valid entry for AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME
50     if (mIndexCur.indexOfKey(device) < 0) {
51         device = AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME;
52     }
53     return mIndexCur.valueFor(device);
54 }
55 
clearCurrentVolumeIndex()56 void StreamDescriptor::clearCurrentVolumeIndex()
57 {
58     mIndexCur.clear();
59 }
60 
addCurrentVolumeIndex(audio_devices_t device,int index)61 void StreamDescriptor::addCurrentVolumeIndex(audio_devices_t device, int index)
62 {
63     mIndexCur.add(device, index);
64 }
65 
setVolumeIndexMin(int volIndexMin)66 void StreamDescriptor::setVolumeIndexMin(int volIndexMin)
67 {
68     mIndexMin = volIndexMin;
69 }
70 
setVolumeIndexMax(int volIndexMax)71 void StreamDescriptor::setVolumeIndexMax(int volIndexMax)
72 {
73     mIndexMax = volIndexMax;
74 }
75 
setVolumeCurvePoint(device_category deviceCategory,const VolumeCurvePoint * point)76 void StreamDescriptor::setVolumeCurvePoint(device_category deviceCategory,
77                                            const VolumeCurvePoint *point)
78 {
79     mVolumeCurve[deviceCategory] = point;
80 }
81 
dump(int fd) const82 void StreamDescriptor::dump(int fd) const
83 {
84     const size_t SIZE = 256;
85     char buffer[SIZE];
86     String8 result;
87 
88     snprintf(buffer, SIZE, "%s         %02d         %02d         ",
89              mCanBeMuted ? "true " : "false", mIndexMin, mIndexMax);
90     result.append(buffer);
91     for (size_t i = 0; i < mIndexCur.size(); i++) {
92         snprintf(buffer, SIZE, "%04x : %02d, ",
93                  mIndexCur.keyAt(i),
94                  mIndexCur.valueAt(i));
95         result.append(buffer);
96     }
97     result.append("\n");
98 
99     write(fd, result.string(), result.size());
100 }
101 
StreamDescriptorCollection()102 StreamDescriptorCollection::StreamDescriptorCollection()
103 {
104     for (size_t stream = 0 ; stream < AUDIO_STREAM_CNT; stream++) {
105         add(static_cast<audio_stream_type_t>(stream), StreamDescriptor());
106     }
107 }
108 
canBeMuted(audio_stream_type_t stream)109 bool StreamDescriptorCollection::canBeMuted(audio_stream_type_t stream)
110 {
111     return valueAt(stream).canBeMuted();
112 }
113 
clearCurrentVolumeIndex(audio_stream_type_t stream)114 void StreamDescriptorCollection::clearCurrentVolumeIndex(audio_stream_type_t stream)
115 {
116     editValueAt(stream).clearCurrentVolumeIndex();
117 }
118 
addCurrentVolumeIndex(audio_stream_type_t stream,audio_devices_t device,int index)119 void StreamDescriptorCollection::addCurrentVolumeIndex(audio_stream_type_t stream,
120                                                        audio_devices_t device, int index)
121 {
122     editValueAt(stream).addCurrentVolumeIndex(device, index);
123 }
124 
setVolumeCurvePoint(audio_stream_type_t stream,device_category deviceCategory,const VolumeCurvePoint * point)125 void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream,
126                                                      device_category deviceCategory,
127                                                      const VolumeCurvePoint *point)
128 {
129     editValueAt(stream).setVolumeCurvePoint(deviceCategory, point);
130 }
131 
getVolumeCurvePoint(audio_stream_type_t stream,device_category deviceCategory) const132 const VolumeCurvePoint *StreamDescriptorCollection::getVolumeCurvePoint(audio_stream_type_t stream,
133                                                                         device_category deviceCategory) const
134 {
135     return valueAt(stream).getVolumeCurvePoint(deviceCategory);
136 }
137 
setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin)138 void StreamDescriptorCollection::setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin)
139 {
140     return editValueAt(stream).setVolumeIndexMin(volIndexMin);
141 }
142 
setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax)143 void StreamDescriptorCollection::setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax)
144 {
145     return editValueAt(stream).setVolumeIndexMax(volIndexMax);
146 }
147 
volIndexToDb(audio_stream_type_t stream,device_category category,int indexInUi) const148 float StreamDescriptorCollection::volIndexToDb(audio_stream_type_t stream, device_category category,
149                                                int indexInUi) const
150 {
151     const StreamDescriptor &streamDesc = valueAt(stream);
152     return Gains::volIndexToDb(streamDesc.getVolumeCurvePoint(category),
153                                streamDesc.getVolumeIndexMin(), streamDesc.getVolumeIndexMax(),
154                                indexInUi);
155 }
156 
initStreamVolume(audio_stream_type_t stream,int indexMin,int indexMax)157 status_t StreamDescriptorCollection::initStreamVolume(audio_stream_type_t stream,
158                                                       int indexMin, int indexMax)
159 {
160     ALOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
161     if (indexMin < 0 || indexMin >= indexMax) {
162         ALOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d",
163               stream , indexMin, indexMax);
164         return BAD_VALUE;
165     }
166     setVolumeIndexMin(stream, indexMin);
167     setVolumeIndexMax(stream, indexMax);
168     return NO_ERROR;
169 }
170 
initializeVolumeCurves(bool isSpeakerDrcEnabled)171 void StreamDescriptorCollection::initializeVolumeCurves(bool isSpeakerDrcEnabled)
172 {
173     for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
174         for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
175             setVolumeCurvePoint(static_cast<audio_stream_type_t>(i),
176                                 static_cast<device_category>(j),
177                                 Gains::sVolumeProfiles[i][j]);
178         }
179     }
180 
181     // Check availability of DRC on speaker path: if available, override some of the speaker curves
182     if (isSpeakerDrcEnabled) {
183         setVolumeCurvePoint(AUDIO_STREAM_SYSTEM, DEVICE_CATEGORY_SPEAKER,
184                             Gains::sDefaultSystemVolumeCurveDrc);
185         setVolumeCurvePoint(AUDIO_STREAM_RING, DEVICE_CATEGORY_SPEAKER,
186                             Gains::sSpeakerSonificationVolumeCurveDrc);
187         setVolumeCurvePoint(AUDIO_STREAM_ALARM, DEVICE_CATEGORY_SPEAKER,
188                             Gains::sSpeakerSonificationVolumeCurveDrc);
189         setVolumeCurvePoint(AUDIO_STREAM_NOTIFICATION, DEVICE_CATEGORY_SPEAKER,
190                             Gains::sSpeakerSonificationVolumeCurveDrc);
191         setVolumeCurvePoint(AUDIO_STREAM_MUSIC, DEVICE_CATEGORY_SPEAKER,
192                             Gains::sSpeakerMediaVolumeCurveDrc);
193         setVolumeCurvePoint(AUDIO_STREAM_ACCESSIBILITY, DEVICE_CATEGORY_SPEAKER,
194                             Gains::sSpeakerMediaVolumeCurveDrc);
195     }
196 }
197 
switchVolumeCurve(audio_stream_type_t streamSrc,audio_stream_type_t streamDst)198 void StreamDescriptorCollection::switchVolumeCurve(audio_stream_type_t streamSrc,
199                                                    audio_stream_type_t streamDst)
200 {
201     for (int j = 0; j < DEVICE_CATEGORY_CNT; j++) {
202         setVolumeCurvePoint(streamDst, static_cast<device_category>(j),
203                             Gains::sVolumeProfiles[streamSrc][j]);
204     }
205 }
206 
dump(int fd) const207 status_t StreamDescriptorCollection::dump(int fd) const
208 {
209     const size_t SIZE = 256;
210     char buffer[SIZE];
211 
212     snprintf(buffer, SIZE, "\nStreams dump:\n");
213     write(fd, buffer, strlen(buffer));
214     snprintf(buffer, SIZE,
215              " Stream  Can be muted  Index Min  Index Max  Index Cur [device : index]...\n");
216     write(fd, buffer, strlen(buffer));
217     for (size_t i = 0; i < size(); i++) {
218         snprintf(buffer, SIZE, " %02zu      ", i);
219         write(fd, buffer, strlen(buffer));
220         valueAt(i).dump(fd);
221     }
222 
223     return NO_ERROR;
224 }
225 
226 }; // namespace android
227