1 /*
2  * Copyright (C) 2023 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 #include <algorithm>
18 #include <cmath>
19 
20 #define LOG_TAG "AHAL_AlsaMixer"
21 #include <android-base/logging.h>
22 #include <android/binder_status.h>
23 #include <error/expected_utils.h>
24 
25 #include "Mixer.h"
26 
27 namespace ndk {
28 
29 // This enables use of 'error/expected_utils' for ScopedAStatus.
30 
errorIsOk(const ScopedAStatus & s)31 inline bool errorIsOk(const ScopedAStatus& s) {
32     return s.isOk();
33 }
34 
errorToString(const ScopedAStatus & s)35 inline std::string errorToString(const ScopedAStatus& s) {
36     return s.getDescription();
37 }
38 
39 }  // namespace ndk
40 
41 namespace aidl::android::hardware::audio::core::alsa {
42 
43 // static
44 const std::map<Mixer::Control, std::vector<Mixer::ControlNamesAndExpectedCtlType>>
45         Mixer::kPossibleControls = {
46                 {Mixer::MASTER_SWITCH, {{"Master Playback Switch", MIXER_CTL_TYPE_BOOL}}},
47                 {Mixer::MASTER_VOLUME, {{"Master Playback Volume", MIXER_CTL_TYPE_INT}}},
48                 {Mixer::HW_VOLUME,
49                  {{"Headphone Playback Volume", MIXER_CTL_TYPE_INT},
50                   {"Headset Playback Volume", MIXER_CTL_TYPE_INT},
51                   {"PCM Playback Volume", MIXER_CTL_TYPE_INT}}},
52                 {Mixer::MIC_SWITCH, {{"Capture Switch", MIXER_CTL_TYPE_BOOL}}},
53                 {Mixer::MIC_GAIN, {{"Capture Volume", MIXER_CTL_TYPE_INT}}}};
54 
55 // static
initializeMixerControls(struct mixer * mixer)56 Mixer::Controls Mixer::initializeMixerControls(struct mixer* mixer) {
57     if (mixer == nullptr) return {};
58     Controls mixerControls;
59     std::string mixerCtlNames;
60     for (const auto& [control, possibleCtls] : kPossibleControls) {
61         for (const auto& [ctlName, expectedCtlType] : possibleCtls) {
62             struct mixer_ctl* ctl = mixer_get_ctl_by_name(mixer, ctlName.c_str());
63             if (ctl != nullptr && mixer_ctl_get_type(ctl) == expectedCtlType) {
64                 mixerControls.emplace(control, ctl);
65                 if (!mixerCtlNames.empty()) {
66                     mixerCtlNames += ",";
67                 }
68                 mixerCtlNames += ctlName;
69                 break;
70             }
71         }
72     }
73     LOG(DEBUG) << __func__ << ": available mixer control names=[" << mixerCtlNames << "]";
74     return mixerControls;
75 }
76 
operator <<(std::ostream & s,Mixer::Control c)77 std::ostream& operator<<(std::ostream& s, Mixer::Control c) {
78     switch (c) {
79         case Mixer::Control::MASTER_SWITCH:
80             s << "master mute";
81             break;
82         case Mixer::Control::MASTER_VOLUME:
83             s << "master volume";
84             break;
85         case Mixer::Control::HW_VOLUME:
86             s << "volume";
87             break;
88         case Mixer::Control::MIC_SWITCH:
89             s << "mic mute";
90             break;
91         case Mixer::Control::MIC_GAIN:
92             s << "mic gain";
93             break;
94     }
95     return s;
96 }
97 
Mixer(int card)98 Mixer::Mixer(int card) : mMixer(mixer_open(card)), mMixerControls(initializeMixerControls(mMixer)) {
99     if (!isValid()) {
100         PLOG(ERROR) << __func__ << ": failed to open mixer for card=" << card;
101     }
102 }
103 
~Mixer()104 Mixer::~Mixer() {
105     if (isValid()) {
106         std::lock_guard l(mMixerAccess);
107         mixer_close(mMixer);
108     }
109 }
110 
getMasterMute(bool * muted)111 ndk::ScopedAStatus Mixer::getMasterMute(bool* muted) {
112     return getMixerControlMute(MASTER_SWITCH, muted);
113 }
114 
getMasterVolume(float * volume)115 ndk::ScopedAStatus Mixer::getMasterVolume(float* volume) {
116     return getMixerControlVolume(MASTER_VOLUME, volume);
117 }
118 
getMicGain(float * gain)119 ndk::ScopedAStatus Mixer::getMicGain(float* gain) {
120     return getMixerControlVolume(MIC_GAIN, gain);
121 }
122 
getMicMute(bool * muted)123 ndk::ScopedAStatus Mixer::getMicMute(bool* muted) {
124     return getMixerControlMute(MIC_SWITCH, muted);
125 }
126 
getVolumes(std::vector<float> * volumes)127 ndk::ScopedAStatus Mixer::getVolumes(std::vector<float>* volumes) {
128     struct mixer_ctl* mctl;
129     RETURN_STATUS_IF_ERROR(findControl(Mixer::HW_VOLUME, &mctl));
130     std::vector<int> percents;
131     std::lock_guard l(mMixerAccess);
132     if (int err = getMixerControlPercent(mctl, &percents); err != 0) {
133         LOG(ERROR) << __func__ << ": failed to get volume, err=" << err;
134         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
135     }
136     std::transform(percents.begin(), percents.end(), std::back_inserter(*volumes),
137                    [](int percent) -> float { return std::clamp(percent / 100.0f, 0.0f, 1.0f); });
138     return ndk::ScopedAStatus::ok();
139 }
140 
setMasterMute(bool muted)141 ndk::ScopedAStatus Mixer::setMasterMute(bool muted) {
142     return setMixerControlMute(MASTER_SWITCH, muted);
143 }
144 
setMasterVolume(float volume)145 ndk::ScopedAStatus Mixer::setMasterVolume(float volume) {
146     return setMixerControlVolume(MASTER_VOLUME, volume);
147 }
148 
setMicGain(float gain)149 ndk::ScopedAStatus Mixer::setMicGain(float gain) {
150     return setMixerControlVolume(MIC_GAIN, gain);
151 }
152 
setMicMute(bool muted)153 ndk::ScopedAStatus Mixer::setMicMute(bool muted) {
154     return setMixerControlMute(MIC_SWITCH, muted);
155 }
156 
setVolumes(const std::vector<float> & volumes)157 ndk::ScopedAStatus Mixer::setVolumes(const std::vector<float>& volumes) {
158     struct mixer_ctl* mctl;
159     RETURN_STATUS_IF_ERROR(findControl(Mixer::HW_VOLUME, &mctl));
160     std::vector<int> percents;
161     std::transform(
162             volumes.begin(), volumes.end(), std::back_inserter(percents),
163             [](float volume) -> int { return std::floor(std::clamp(volume, 0.0f, 1.0f) * 100); });
164     std::lock_guard l(mMixerAccess);
165     if (int err = setMixerControlPercent(mctl, percents); err != 0) {
166         LOG(ERROR) << __func__ << ": failed to set volume, err=" << err;
167         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
168     }
169     return ndk::ScopedAStatus::ok();
170 }
171 
findControl(Control ctl,struct mixer_ctl ** result)172 ndk::ScopedAStatus Mixer::findControl(Control ctl, struct mixer_ctl** result) {
173     if (!isValid()) {
174         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
175     }
176     if (auto it = mMixerControls.find(ctl); it != mMixerControls.end()) {
177         *result = it->second;
178         return ndk::ScopedAStatus::ok();
179     }
180     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
181 }
182 
getMixerControlMute(Control ctl,bool * muted)183 ndk::ScopedAStatus Mixer::getMixerControlMute(Control ctl, bool* muted) {
184     struct mixer_ctl* mctl;
185     RETURN_STATUS_IF_ERROR(findControl(ctl, &mctl));
186     std::lock_guard l(mMixerAccess);
187     std::vector<int> mutedValues;
188     if (int err = getMixerControlValues(mctl, &mutedValues); err != 0) {
189         LOG(ERROR) << __func__ << ": failed to get " << ctl << ", err=" << err;
190         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
191     }
192     if (mutedValues.empty()) {
193         LOG(ERROR) << __func__ << ": got no values for " << ctl;
194         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
195     }
196     *muted = mutedValues[0] != 0;
197     return ndk::ScopedAStatus::ok();
198 }
199 
getMixerControlVolume(Control ctl,float * volume)200 ndk::ScopedAStatus Mixer::getMixerControlVolume(Control ctl, float* volume) {
201     struct mixer_ctl* mctl;
202     RETURN_STATUS_IF_ERROR(findControl(ctl, &mctl));
203     std::lock_guard l(mMixerAccess);
204     std::vector<int> percents;
205     if (int err = getMixerControlPercent(mctl, &percents); err != 0) {
206         LOG(ERROR) << __func__ << ": failed to get " << ctl << ", err=" << err;
207         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
208     }
209     if (percents.empty()) {
210         LOG(ERROR) << __func__ << ": got no values for " << ctl;
211         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
212     }
213     *volume = std::clamp(percents[0] / 100.0f, 0.0f, 1.0f);
214     return ndk::ScopedAStatus::ok();
215 }
216 
setMixerControlMute(Control ctl,bool muted)217 ndk::ScopedAStatus Mixer::setMixerControlMute(Control ctl, bool muted) {
218     struct mixer_ctl* mctl;
219     RETURN_STATUS_IF_ERROR(findControl(ctl, &mctl));
220     std::lock_guard l(mMixerAccess);
221     if (int err = setMixerControlValue(mctl, muted ? 0 : 1); err != 0) {
222         LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << muted << ", err=" << err;
223         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
224     }
225     return ndk::ScopedAStatus::ok();
226 }
227 
setMixerControlVolume(Control ctl,float volume)228 ndk::ScopedAStatus Mixer::setMixerControlVolume(Control ctl, float volume) {
229     struct mixer_ctl* mctl;
230     RETURN_STATUS_IF_ERROR(findControl(ctl, &mctl));
231     volume = std::clamp(volume, 0.0f, 1.0f);
232     std::lock_guard l(mMixerAccess);
233     if (int err = setMixerControlPercent(mctl, std::floor(volume * 100)); err != 0) {
234         LOG(ERROR) << __func__ << ": failed to set " << ctl << " to " << volume << ", err=" << err;
235         return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
236     }
237     return ndk::ScopedAStatus::ok();
238 }
239 
getMixerControlPercent(struct mixer_ctl * ctl,std::vector<int> * percents)240 int Mixer::getMixerControlPercent(struct mixer_ctl* ctl, std::vector<int>* percents) {
241     const unsigned int n = mixer_ctl_get_num_values(ctl);
242     percents->resize(n);
243     for (unsigned int id = 0; id < n; id++) {
244         if (int valueOrError = mixer_ctl_get_percent(ctl, id); valueOrError >= 0) {
245             (*percents)[id] = valueOrError;
246         } else {
247             return valueOrError;
248         }
249     }
250     return 0;
251 }
252 
getMixerControlValues(struct mixer_ctl * ctl,std::vector<int> * values)253 int Mixer::getMixerControlValues(struct mixer_ctl* ctl, std::vector<int>* values) {
254     const unsigned int n = mixer_ctl_get_num_values(ctl);
255     values->resize(n);
256     for (unsigned int id = 0; id < n; id++) {
257         if (int valueOrError = mixer_ctl_get_value(ctl, id); valueOrError >= 0) {
258             (*values)[id] = valueOrError;
259         } else {
260             return valueOrError;
261         }
262     }
263     return 0;
264 }
265 
setMixerControlPercent(struct mixer_ctl * ctl,int percent)266 int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, int percent) {
267     const unsigned int n = mixer_ctl_get_num_values(ctl);
268     for (unsigned int id = 0; id < n; id++) {
269         if (int error = mixer_ctl_set_percent(ctl, id, percent); error != 0) {
270             return error;
271         }
272     }
273     return 0;
274 }
275 
setMixerControlPercent(struct mixer_ctl * ctl,const std::vector<int> & percents)276 int Mixer::setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) {
277     const unsigned int n = mixer_ctl_get_num_values(ctl);
278     for (unsigned int id = 0; id < n; id++) {
279         if (int error = mixer_ctl_set_percent(ctl, id, id < percents.size() ? percents[id] : 0);
280             error != 0) {
281             return error;
282         }
283     }
284     return 0;
285 }
286 
setMixerControlValue(struct mixer_ctl * ctl,int value)287 int Mixer::setMixerControlValue(struct mixer_ctl* ctl, int value) {
288     const unsigned int n = mixer_ctl_get_num_values(ctl);
289     for (unsigned int id = 0; id < n; id++) {
290         if (int error = mixer_ctl_set_value(ctl, id, value); error != 0) {
291             return error;
292         }
293     }
294     return 0;
295 }
296 
297 }  // namespace aidl::android::hardware::audio::core::alsa
298