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
33namespace android {
34
35// --- StreamDescriptor class implementation
36
37StreamDescriptor::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
46int 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
56void StreamDescriptor::clearCurrentVolumeIndex()
57{
58    mIndexCur.clear();
59}
60
61void StreamDescriptor::addCurrentVolumeIndex(audio_devices_t device, int index)
62{
63    mIndexCur.add(device, index);
64}
65
66void StreamDescriptor::setVolumeIndexMin(int volIndexMin)
67{
68    mIndexMin = volIndexMin;
69}
70
71void StreamDescriptor::setVolumeIndexMax(int volIndexMax)
72{
73    mIndexMax = volIndexMax;
74}
75
76void StreamDescriptor::setVolumeCurvePoint(device_category deviceCategory,
77                                           const VolumeCurvePoint *point)
78{
79    mVolumeCurve[deviceCategory] = point;
80}
81
82void 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
102StreamDescriptorCollection::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
109bool StreamDescriptorCollection::canBeMuted(audio_stream_type_t stream)
110{
111    return valueAt(stream).canBeMuted();
112}
113
114void StreamDescriptorCollection::clearCurrentVolumeIndex(audio_stream_type_t stream)
115{
116    editValueAt(stream).clearCurrentVolumeIndex();
117}
118
119void StreamDescriptorCollection::addCurrentVolumeIndex(audio_stream_type_t stream,
120                                                       audio_devices_t device, int index)
121{
122    editValueAt(stream).addCurrentVolumeIndex(device, index);
123}
124
125void StreamDescriptorCollection::setVolumeCurvePoint(audio_stream_type_t stream,
126                                                     device_category deviceCategory,
127                                                     const VolumeCurvePoint *point)
128{
129    editValueAt(stream).setVolumeCurvePoint(deviceCategory, point);
130}
131
132const VolumeCurvePoint *StreamDescriptorCollection::getVolumeCurvePoint(audio_stream_type_t stream,
133                                                                        device_category deviceCategory) const
134{
135    return valueAt(stream).getVolumeCurvePoint(deviceCategory);
136}
137
138void StreamDescriptorCollection::setVolumeIndexMin(audio_stream_type_t stream,int volIndexMin)
139{
140    return editValueAt(stream).setVolumeIndexMin(volIndexMin);
141}
142
143void StreamDescriptorCollection::setVolumeIndexMax(audio_stream_type_t stream,int volIndexMax)
144{
145    return editValueAt(stream).setVolumeIndexMax(volIndexMax);
146}
147
148float 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
157status_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
171void 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
198void 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
207status_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