• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "DeviceDescriptor.h"
20 #include "PolicyAudioPort.h"
21 #include "policy.h"
22 #include <media/AudioContainers.h>
23 #include <utils/String8.h>
24 #include <system/audio.h>
25 
26 namespace android {
27 
28 class HwModule;
29 
30 // the IOProfile class describes the capabilities of an output or input stream.
31 // It is currently assumed that all combination of listed parameters are supported.
32 // It is used by the policy manager to determine if an output or input is suitable for
33 // a given use case,  open/close it accordingly and connect/disconnect audio tracks
34 // to/from it.
35 class IOProfile : public AudioPort, public PolicyAudioPort
36 {
37 public:
38     IOProfile(const std::string &name, audio_port_role_t role);
39 
40     virtual ~IOProfile() = default;
41 
42     // For a Profile aka MixPort, tag name and name are equivalent.
getTagName()43     virtual const std::string getTagName() const { return getName(); }
44 
addAudioProfile(const sp<AudioProfile> & profile)45     virtual void addAudioProfile(const sp<AudioProfile> &profile) {
46         addAudioProfileAndSort(mProfiles, profile);
47     }
48 
asAudioPort()49     virtual sp<AudioPort> asAudioPort() const {
50         return static_cast<AudioPort*>(const_cast<IOProfile*>(this));
51     }
52 
53     // FIXME: this is needed because shared MMAP stream clients use the same audio session.
54     // Once capture clients are tracked individually and not per session this can be removed
55     // MMAP no IRQ input streams do not have the default limitation of one active client
56     // max as they can be used in shared mode by the same application.
57     // NOTE: Please consider moving to AudioPort when addressing the FIXME
58     // NOTE: this works for explicit values set in audio_policy_configuration.xml because
59     // flags are parsed before maxActiveCount by the serializer.
setFlags(uint32_t flags)60     void setFlags(uint32_t flags) override
61     {
62         AudioPort::setFlags(flags);
63         if (getRole() == AUDIO_PORT_ROLE_SINK && (flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
64             maxActiveCount = 0;
65         }
66         refreshMixerBehaviors();
67     }
68 
getMixerBehaviors()69     const MixerBehaviorSet& getMixerBehaviors() const {
70         return mMixerBehaviors;
71     }
72 
73     /**
74      * NO_MATCH: Both config and flags are not compatible.
75      * PARTIAL_MATCH: Both config and flags are partially matched.
76      * PARTIAL_MATCH_WITH_CONFIG: Partial match with flags(e.g. fast flags) and exact match with
77      * config.
78      * PARTIAL_MATCH_WITH_FLAG: Partial match with config and exact match with flags.
79      * EXACT_MATCH: Both config and flags are exactly matched.
80      */
81     enum CompatibilityScore{
82         NO_MATCH = 0,
83         PARTIAL_MATCH = 1,
84         PARTIAL_MATCH_WITH_CONFIG = 2,
85         PARTIAL_MATCH_WITH_FLAG = 3,
86         EXACT_MATCH = 4
87     };
88 
89     /**
90      * @brief compatibilityScore: This method is used for input and direct output,
91      * and is not used for other output.
92      * Return the compatibility score to measure how much the IO profile is compatible
93      * with specified parameters.
94      * For input, flags is interpreted as audio_input_flags_t.
95      * TODO: merge audio_output_flags_t and audio_input_flags_t.
96      *
97      * @param devices vector of devices to be checked for compatibility
98      * @param samplingRate to be checked for compatibility. Must be specified
99      * @param updatedSamplingRate if non-NULL, it is assigned the actual sample rate.
100      * @param format to be checked for compatibility. Must be specified
101      * @param updatedFormat if non-NULL, it is assigned the actual format
102      * @param channelMask to be checked for compatibility. Must be specified
103      * @param updatedChannelMask if non-NULL, it is assigned the actual channel mask
104      * @param flags to be checked for compatibility
105      * @return how the IO profile is compatible with the given parameters.
106      */
107     CompatibilityScore getCompatibilityScore(const DeviceVector &devices,
108                                              uint32_t samplingRate,
109                                              uint32_t *updatedSamplingRate,
110                                              audio_format_t format,
111                                              audio_format_t *updatedFormat,
112                                              audio_channel_mask_t channelMask,
113                                              audio_channel_mask_t *updatedChannelMask,
114                                              // FIXME parameter type
115                                              uint32_t flags) const;
116 
117     /**
118      * @brief areAllDevicesSupported: Checks if the given devices are supported by the IO profile.
119      *
120      * @param devices vector of devices to be checked for compatibility
121      * @return true if all devices are supported, false otherwise.
122      */
123     bool areAllDevicesSupported(const DeviceVector &devices) const;
124 
125     /**
126      * @brief isCompatibleProfileForFlags: Checks if the IO profile is compatible with
127      * specified flags.
128      *
129      * @param flags to be checked for compatibility
130      * @return true if the profile is compatible, false otherwise.
131      */
132     bool isCompatibleProfileForFlags(uint32_t flags) const;
133 
134     void dump(String8 *dst, int spaces) const;
135     void log();
136 
hasSupportedDevices()137     bool hasSupportedDevices() const { return !mSupportedDevices.isEmpty(); }
138 
supportsDeviceTypes(const DeviceTypeSet & deviceTypes)139     bool supportsDeviceTypes(const DeviceTypeSet& deviceTypes) const
140     {
141         const bool areOutputDevices = Intersection(deviceTypes, getAudioDeviceInAllSet()).empty();
142         const bool devicesSupported = !mSupportedDevices.getDevicesFromTypes(deviceTypes).empty();
143         return devicesSupported &&
144                (!areOutputDevices || devicesSupportEncodedFormats(deviceTypes));
145     }
146 
147     /**
148      * @brief getTag
149      * @param deviceTypes to be considered
150      * @return tagName of first matching device for the considered types, empty string otherwise.
151      */
getTag(const DeviceTypeSet & deviceTypes)152     std::string getTag(const DeviceTypeSet& deviceTypes) const
153     {
154         if (supportsDeviceTypes(deviceTypes)) {
155             return mSupportedDevices.getDevicesFromTypes(deviceTypes).itemAt(0)->getTagName();
156         }
157         return {};
158     }
159 
160     /**
161      * @brief supportsDevice
162      * @param device to be checked against
163      *        forceCheckOnAddress if true, check on type and address whatever the type, otherwise
164      *        the address enforcement is limited to "offical devices" that distinguishe on address
165      * @return true if the device is supported by type (for non bus / remote submix devices),
166      *         true if the device is supported (both type and address) for bus / remote submix
167      *         false otherwise
168      */
169     bool supportsDevice(const sp<DeviceDescriptor> &device, bool forceCheckOnAddress = false) const
170     {
171         if (!device_distinguishes_on_address(device->type()) && !forceCheckOnAddress) {
172             return supportsDeviceTypes(DeviceTypeSet({device->type()}));
173         }
174         return mSupportedDevices.contains(device);
175     }
176 
devicesSupportEncodedFormats(DeviceTypeSet deviceTypes)177     bool devicesSupportEncodedFormats(DeviceTypeSet deviceTypes) const
178     {
179         if (deviceTypes.empty()) {
180             return true; // required for getOffloadSupport() check
181         }
182         DeviceVector deviceList =
183             mSupportedDevices.getDevicesFromTypes(deviceTypes);
184         for (const auto& device : deviceList) {
185             if (device->hasCurrentEncodedFormat()) {
186                 return true;
187             }
188         }
189         return false;
190     }
191 
192     bool containsSingleDeviceSupportingEncodedFormats(const sp<DeviceDescriptor>& device) const;
193 
clearSupportedDevices()194     void clearSupportedDevices() { mSupportedDevices.clear(); }
addSupportedDevice(const sp<DeviceDescriptor> & device)195     void addSupportedDevice(const sp<DeviceDescriptor> &device)
196     {
197         mSupportedDevices.add(device);
198     }
removeSupportedDevice(const sp<DeviceDescriptor> & device)199     void removeSupportedDevice(const sp<DeviceDescriptor> &device)
200     {
201         ssize_t ret = mSupportedDevices.indexOf(device);
202         if (ret >= 0 && !mSupportedDevices.itemAt(ret)->isDynamic()) {
203             // devices equality checks only type, address, name and format
204             // Prevents from removing non dynamically added devices
205             return;
206         }
207         mSupportedDevices.remove(device);
208     }
setSupportedDevices(const DeviceVector & devices)209     void setSupportedDevices(const DeviceVector &devices)
210     {
211         mSupportedDevices = devices;
212     }
213 
getSupportedDevices()214     const DeviceVector &getSupportedDevices() const { return mSupportedDevices; }
215 
canOpenNewIo()216     bool canOpenNewIo() {
217         if (maxOpenCount == 0 || curOpenCount < maxOpenCount) {
218             return true;
219         }
220         return false;
221     }
222 
canStartNewIo()223     bool canStartNewIo() {
224         if (maxActiveCount == 0 || curActiveCount < maxActiveCount) {
225             return true;
226         }
227         return false;
228     }
229 
230     void toSupportedMixerAttributes(std::vector<audio_mixer_attributes_t>* mixerAttributes) const;
231 
232     status_t readFromParcelable(const media::AudioPortFw& parcelable);
233 
234     void importAudioPort(const audio_port_v7& port) override;
235 
236     // Number of streams currently opened for this profile.
237     uint32_t     curOpenCount;
238     // Number of streams currently active for this profile. This is not the number of active clients
239     // (AudioTrack or AudioRecord) but the number of active HAL streams.
240     uint32_t     curActiveCount;
241 
242 private:
243     void refreshMixerBehaviors();
244     CompatibilityScore getFlagsCompatibleScore(uint32_t flags) const;
245 
246     DeviceVector mSupportedDevices; // supported devices: this input/output can be routed from/to
247 
248     MixerBehaviorSet mMixerBehaviors;
249 };
250 
251 class InputProfile : public IOProfile
252 {
253 public:
InputProfile(const std::string & name)254     explicit InputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SINK) {}
255 };
256 
257 class OutputProfile : public IOProfile
258 {
259 public:
OutputProfile(const std::string & name)260     explicit OutputProfile(const std::string &name) : IOProfile(name, AUDIO_PORT_ROLE_SOURCE) {}
261 };
262 
263 } // namespace android
264