• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 setMasterMute(bool muted);
43     ndk::ScopedAStatus setMasterVolume(float volume);
44     ndk::ScopedAStatus setMicGain(float gain);
45     ndk::ScopedAStatus setMicMute(bool muted);
46     ndk::ScopedAStatus setVolumes(const std::vector<float>& volumes);
47 
48   private:
49     enum Control {
50         MASTER_SWITCH,
51         MASTER_VOLUME,
52         HW_VOLUME,
53         MIC_SWITCH,
54         MIC_GAIN,
55     };
56     using ControlNamesAndExpectedCtlType = std::pair<std::string, enum mixer_ctl_type>;
57     using Controls = std::map<Control, struct mixer_ctl*>;
58 
59     friend std::ostream& operator<<(std::ostream&, Control);
60     static const std::map<Control, std::vector<ControlNamesAndExpectedCtlType>> kPossibleControls;
61     static Controls initializeMixerControls(struct mixer* mixer);
62 
63     ndk::ScopedAStatus setMixerControlMute(Control ctl, bool muted);
64     ndk::ScopedAStatus setMixerControlVolume(Control ctl, float volume);
65 
66     int setMixerControlPercent(struct mixer_ctl* ctl, int percent) REQUIRES(mMixerAccess);
67     int setMixerControlPercent(struct mixer_ctl* ctl, const std::vector<int>& percents)
68             REQUIRES(mMixerAccess);
69     int setMixerControlValue(struct mixer_ctl* ctl, int value) REQUIRES(mMixerAccess);
70 
71     // Since ALSA functions do not use internal locking, enforce thread safety at our level.
72     std::mutex mMixerAccess;
73     // The mixer object is owned by ALSA and will be released when the mixer is closed.
74     struct mixer* const mMixer;
75     // `mMixerControls` will only be initialized in constructor. After that, it will only be
76     // read but not be modified. Each mixer_ctl object is owned by ALSA, it's life span is
77     // the same as of the mixer itself.
78     const Controls mMixerControls;
79 };
80 
81 }  // namespace aidl::android::hardware::audio::core::alsa
82