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 #pragma once 18 19 #include <iostream> 20 #include <map> 21 #include <memory> 22 #include <mutex> 23 #include <string> 24 #include <vector> 25 26 #include <android-base/thread_annotations.h> 27 #include <android/binder_auto_utils.h> 28 29 extern "C" { 30 #include <tinyalsa/mixer.h> 31 } 32 33 namespace aidl::android::hardware::audio::core::alsa { 34 35 class Mixer { 36 public: 37 explicit Mixer(int card); 38 ~Mixer(); 39 isValid()40 bool isValid() const { return mMixer != nullptr; } 41 42 ndk::ScopedAStatus getMasterMute(bool* muted); 43 ndk::ScopedAStatus getMasterVolume(float* volume); 44 ndk::ScopedAStatus getMicGain(float* gain); 45 ndk::ScopedAStatus getMicMute(bool* muted); 46 ndk::ScopedAStatus getVolumes(std::vector<float>* volumes); 47 ndk::ScopedAStatus setMasterMute(bool muted); 48 ndk::ScopedAStatus setMasterVolume(float volume); 49 ndk::ScopedAStatus setMicGain(float gain); 50 ndk::ScopedAStatus setMicMute(bool muted); 51 ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes); 52 53 private: 54 enum Control { 55 MASTER_SWITCH, 56 MASTER_VOLUME, 57 HW_VOLUME, 58 MIC_SWITCH, 59 MIC_GAIN, 60 }; 61 using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>; 62 using Controls = std::map<Control, struct mixer_ctl*>; 63 64 friend std::ostream& operator<<(std::ostream&, Control); 65 static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls; 66 static Controls initializeMixerControls(struct mixer* mixer); 67 68 ndk::ScopedAStatus findControl(Control ctl, struct mixer_ctl** result); 69 ndk::ScopedAStatus getMixerControlMute(Control ctl, bool* muted); 70 ndk::ScopedAStatus getMixerControlVolume(Control ctl, float* volume); 71 ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted); 72 ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume); 73 74 int getMixerControlPercent(struct mixer_ctl* ctl, std::vector<int>* percents) 75 REQUIRES(mMixerAccess); 76 int getMixerControlValues(struct mixer_ctl* ctl, std::vector<int>* values) 77 REQUIRES(mMixerAccess); 78 int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess); 79 int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents) 80 REQUIRES(mMixerAccess); 81 int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess); 82 83 // Since ALSA functions do not use internal locking, enforce thread safety at our level. 84 std::mutex mMixerAccess; 85 // The mixer object is owned by ALSA and will be released when the mixer is closed. 86 struct mixer* const mMixer; 87 // `mMixerControls` will only be initialized in constructor. After that, it will only be 88 // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is 89 // the same as of the mixer itself. 90 const Controls mMixerControls; 91 }; 92 93 } // namespace aidl::android::hardware::audio::core::alsa 94