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 #pragma once
18 
19 #include "AudioCollections.h"
20 #include "AudioProfileVectorHelper.h"
21 #include "HandleGenerator.h"
22 #include <media/AudioGain.h>
23 #include <media/AudioPort.h>
24 #include <utils/String8.h>
25 #include <utils/Vector.h>
26 #include <utils/RefBase.h>
27 #include <utils/Errors.h>
28 #include <system/audio.h>
29 #include <cutils/config_utils.h>
30 
31 namespace android {
32 
33 class HwModule;
34 class AudioRoute;
35 
36 class PolicyAudioPort : public virtual RefBase, private HandleGenerator<audio_port_handle_t>
37 {
38 public:
PolicyAudioPort()39     PolicyAudioPort() : mFlags(AUDIO_OUTPUT_FLAG_NONE) {}
40 
41     virtual ~PolicyAudioPort() = default;
42 
43     virtual const std::string getTagName() const = 0;
44 
45     virtual sp<AudioPort> asAudioPort() const = 0;
46 
setFlags(uint32_t flags)47     virtual void setFlags(uint32_t flags)
48     {
49         //force direct flag if offload flag is set: offloading implies a direct output stream
50         // and all common behaviors are driven by checking only the direct flag
51         // this should normally be set appropriately in the policy configuration file
52         if (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE &&
53                 (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
54             flags |= AUDIO_OUTPUT_FLAG_DIRECT;
55         }
56         mFlags = flags;
57     }
getFlags()58     uint32_t getFlags() const { return mFlags; }
59 
60     virtual void attach(const sp<HwModule>& module);
61     virtual void detach();
isAttached()62     bool isAttached() { return mModule != 0; }
63 
64     // Audio port IDs are in a different namespace than AudioFlinger unique IDs
65     static audio_port_handle_t getNextUniqueId();
66 
67     // searches for an exact match
68     virtual status_t checkExactAudioProfile(const struct audio_port_config *config) const;
69 
70     // searches for a compatible match, currently implemented for input
71     // parameters are input|output, returned value is the best match.
checkCompatibleAudioProfile(uint32_t & samplingRate,audio_channel_mask_t & channelMask,audio_format_t & format)72     status_t checkCompatibleAudioProfile(uint32_t &samplingRate,
73                                          audio_channel_mask_t &channelMask,
74                                          audio_format_t &format) const
75     {
76         return checkCompatibleProfile(
77                 asAudioPort()->getAudioProfiles(), samplingRate, channelMask, format,
78                 asAudioPort()->getType(), asAudioPort()->getRole());
79     }
80 
81     void pickAudioProfile(uint32_t &samplingRate,
82                           audio_channel_mask_t &channelMask,
83                           audio_format_t &format) const;
84 
85     static const audio_format_t sPcmFormatCompareTable[];
86 
87     static int compareFormats(audio_format_t format1, audio_format_t format2);
88 
89     // Used to select an audio HAL output stream with a sample format providing the
90     // less degradation for a given AudioTrack sample format.
91     static bool isBetterFormatMatch(audio_format_t newFormat,
92                                     audio_format_t currentFormat,
93                                     audio_format_t targetFormat);
94     static uint32_t formatDistance(audio_format_t format1,
95                                    audio_format_t format2);
96     static const uint32_t kFormatDistanceMax = 4;
97 
98     audio_module_handle_t getModuleHandle() const;
99     uint32_t getModuleVersionMajor() const;
100     const char *getModuleName() const;
getModule()101     sp<HwModule> getModule() const { return mModule; }
102 
isDirectOutput()103     inline bool isDirectOutput() const
104     {
105         return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX) &&
106                 (asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
107                 (mFlags & (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD));
108     }
109 
isMmap()110     inline bool isMmap() const
111     {
112         return (asAudioPort()->getType() == AUDIO_PORT_TYPE_MIX)
113                 && (((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SOURCE) &&
114                         ((mFlags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) != 0))
115                     || ((asAudioPort()->getRole() == AUDIO_PORT_ROLE_SINK) &&
116                         ((mFlags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)));
117     }
118 
addRoute(const sp<AudioRoute> & route)119     void addRoute(const sp<AudioRoute> &route) { mRoutes.add(route); }
getRoutes()120     const AudioRouteVector &getRoutes() const { return mRoutes; }
121 
122 private:
123     void pickChannelMask(audio_channel_mask_t &channelMask,
124                          const ChannelMaskSet &channelMasks) const;
125     void pickSamplingRate(uint32_t &rate, const SampleRateSet &samplingRates) const;
126 
127     uint32_t mFlags; // attribute flags mask (e.g primary output, direct output...).
128     sp<HwModule> mModule;     // audio HW module exposing this I/O stream
129     AudioRouteVector mRoutes; // Routes involving this port
130 };
131 
132 class PolicyAudioPortConfig : public virtual RefBase
133 {
134 public:
135     virtual ~PolicyAudioPortConfig() = default;
136 
137     virtual sp<PolicyAudioPort> getPolicyAudioPort() const = 0;
138 
139     status_t validationBeforeApplyConfig(const struct audio_port_config *config) const;
140 
applyPolicyAudioPortConfig(const struct audio_port_config * config)141     void applyPolicyAudioPortConfig(const struct audio_port_config *config) {
142         if (config->config_mask & AUDIO_PORT_CONFIG_FLAGS) {
143             mFlags = config->flags;
144         }
145     }
146 
147     void toPolicyAudioPortConfig(
148             struct audio_port_config *dstConfig,
149             const struct audio_port_config *srcConfig = NULL) const;
150 
151 
hasSameHwModuleAs(const sp<PolicyAudioPortConfig> & other)152     virtual bool hasSameHwModuleAs(const sp<PolicyAudioPortConfig>& other) const {
153         return (other.get() != nullptr) && (other->getPolicyAudioPort().get() != nullptr) &&
154                 (getPolicyAudioPort().get() != nullptr) &&
155                 (other->getPolicyAudioPort()->getModuleHandle() ==
156                         getPolicyAudioPort()->getModuleHandle());
157     }
158 
159     union audio_io_flags mFlags = { AUDIO_INPUT_FLAG_NONE };
160 };
161 
162 } // namespace android
163