• Home
  • History
  • Annotate
  • 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 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