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::AudioPolicyEngine/Stream"
18 
19 #include "Stream.h"
20 #include <system/audio.h>
21 
22 using std::string;
23 
24 namespace android
25 {
26 namespace audio_policy
27 {
28 
setIdentifier(audio_stream_type_t identifier)29 status_t Element<audio_stream_type_t>::setIdentifier(audio_stream_type_t identifier)
30 {
31     if (identifier > AUDIO_STREAM_CNT) {
32         return BAD_VALUE;
33     }
34     mIdentifier = identifier;
35     ALOGD("%s: Stream %s identifier 0x%X", __FUNCTION__, getName().c_str(), identifier);
36     return NO_ERROR;
37 }
38 
39 /**
40 * Set the strategy to follow for this stream.
41 * It checks if the strategy is valid.
42 *
43 * @param[in] strategy to be followed.
44 *
45 * @return NO_ERROR if the strategy is set correctly, error code otherwise.
46 */
47 template <>
set(routing_strategy strategy)48 status_t Element<audio_stream_type_t>::set<routing_strategy>(routing_strategy strategy)
49 {
50     if (strategy >= NUM_STRATEGIES) {
51         return BAD_VALUE;
52     }
53     mApplicableStrategy = strategy;
54     ALOGD("%s: 0x%X for Stream %s", __FUNCTION__, strategy, getName().c_str());
55     return NO_ERROR;
56 }
57 
58 template <>
get() const59 routing_strategy Element<audio_stream_type_t>::get<routing_strategy>() const
60 {
61     ALOGV("%s: 0x%X for Stream %s", __FUNCTION__, mApplicableStrategy, getName().c_str());
62     return mApplicableStrategy;
63 }
64 
setVolumeProfile(Volume::device_category category,const VolumeCurvePoints & points)65 status_t Element<audio_stream_type_t>::setVolumeProfile(Volume::device_category category,
66                                                         const VolumeCurvePoints &points)
67 {
68     ALOGD("%s: adding volume profile for %s for device category %d, points nb =%d", __FUNCTION__,
69           getName().c_str(), category, points.size());
70     mVolumeProfiles[category] = points;
71 
72     for (size_t i = 0; i < points.size(); i++) {
73         ALOGV("%s: %s cat=%d curve index =%d Index=%d dBAttenuation=%f",
74               __FUNCTION__, getName().c_str(), category, i, points[i].mIndex,
75              points[i].mDBAttenuation);
76     }
77     return NO_ERROR;
78 }
79 
initVolume(int indexMin,int indexMax)80 status_t Element<audio_stream_type_t>::initVolume(int indexMin, int indexMax)
81 {
82     ALOGV("initStreamVolume() stream %s, min %d, max %d", getName().c_str(), indexMin, indexMax);
83     if (indexMin < 0 || indexMin >= indexMax) {
84         ALOGW("initStreamVolume() invalid index limits for stream %s, min %d, max %d",
85               getName().c_str(), indexMin, indexMax);
86         return BAD_VALUE;
87     }
88     mIndexMin = indexMin;
89     mIndexMax = indexMax;
90 
91     return NO_ERROR;
92 }
93 
volIndexToDb(Volume::device_category deviceCategory,int indexInUi)94 float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceCategory,
95                                                    int indexInUi)
96 {
97     VolumeProfileConstIterator it = mVolumeProfiles.find(deviceCategory);
98     if (it == mVolumeProfiles.end()) {
99         ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
100               getName().c_str());
101         return 1.0f;
102     }
103     const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
104     if (curve.size() != Volume::VOLCNT) {
105         ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
106               getName().c_str());
107         return 1.0f;
108     }
109 
110     // the volume index in the UI is relative to the min and max volume indices for this stream type
111     int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
112             curve[Volume::VOLMIN].mIndex;
113 
114     if (mIndexMax - mIndexMin == 0) {
115         ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
116         return 1.0f;
117     }
118     int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
119             (mIndexMax - mIndexMin);
120 
121     // find what part of the curve this index volume belongs to, or if it's out of bounds
122     int segment = 0;
123     if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
124         return 0.0f;
125     } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
126         segment = 0;
127     } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
128         segment = 1;
129     } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
130         segment = 2;
131     } else {                                                               // out of bounds
132         return 1.0f;
133     }
134 
135     // linear interpolation in the attenuation table in dB
136     float decibels = curve[segment].mDBAttenuation +
137             ((float)(volIdx - curve[segment].mIndex)) *
138                 ( (curve[segment+1].mDBAttenuation -
139                         curve[segment].mDBAttenuation) /
140                     ((float)(curve[segment+1].mIndex -
141                             curve[segment].mIndex)) );
142 
143     ALOGV("VOLUME vol index=[%d %d %d], dB=[%.1f %.1f %.1f]",
144             curve[segment].mIndex, volIdx,
145             curve[segment+1].mIndex,
146             curve[segment].mDBAttenuation,
147             decibels,
148             curve[segment+1].mDBAttenuation);
149 
150     return decibels;
151 }
152 
153 } // namespace audio_policy
154 } // namespace android
155 
156