xref: /aosp_15_r20/frameworks/av/services/audioflinger/datapath/AudioHwDevice.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  *
3  * Copyright 2007, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #define LOG_TAG "AudioHwDevice"
19 //#define LOG_NDEBUG 0
20 
21 #include <system/audio.h>
22 #include <utils/Log.h>
23 
24 #include <audio_utils/spdif/SPDIFDecoder.h>
25 #include <audio_utils/spdif/SPDIFEncoder.h>
26 #include <media/AudioResamplerPublic.h>
27 
28 #include "AudioHwDevice.h"
29 #include "AudioStreamOut.h"
30 #include "SpdifStreamIn.h"
31 #include "SpdifStreamOut.h"
32 
33 namespace android {
34 
35 using media::audio::common::AudioMMapPolicyInfo;
36 using media::audio::common::AudioMMapPolicyType;
37 
38 // ----------------------------------------------------------------------------
39 
openOutputStream(AudioStreamOut ** ppStreamOut,audio_io_handle_t handle,audio_devices_t deviceType,audio_output_flags_t * flags,struct audio_config * config,const char * address,const std::vector<playback_track_metadata_v7_t> & sourceMetadata)40 status_t AudioHwDevice::openOutputStream(
41         AudioStreamOut **ppStreamOut,
42         audio_io_handle_t handle,
43         audio_devices_t deviceType,
44         audio_output_flags_t *flags,
45         struct audio_config *config,
46         const char *address,
47         const std::vector<playback_track_metadata_v7_t>& sourceMetadata)
48 {
49 
50     struct audio_config originalConfig = *config;
51     auto outputStream = new AudioStreamOut(this);
52 
53     // Try to open the HAL first using the current format.
54     ALOGV("openOutputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
55             config->format, config->channel_mask);
56     status_t status = outputStream->open(handle, deviceType, config, flags, address,
57                                         sourceMetadata);
58 
59     if (status != NO_ERROR) {
60         delete outputStream;
61         outputStream = nullptr;
62 
63         // FIXME Look at any modification to the config.
64         // The HAL might modify the config to suggest a wrapped format.
65         // Log this so we can see what the HALs are doing.
66         ALOGI("openOutputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
67                 " status %d", config->sample_rate, config->format, config->channel_mask, status);
68 
69         // If the data is encoded then try again using wrapped PCM.
70         const bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
71                 && ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
72                 && ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);
73 
74         if (wrapperNeeded) {
75             if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
76                 outputStream = new SpdifStreamOut(this, originalConfig.format);
77                 status = outputStream->open(handle, deviceType, &originalConfig, flags, address,
78                                             sourceMetadata);
79                 if (status != NO_ERROR) {
80                     ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
81                         status);
82                     delete outputStream;
83                     outputStream = nullptr;
84                 } else {
85                     // on success, we need to assign the actual HAL stream config so that clients
86                     // know and can later patch correctly.
87                     config->format = originalConfig.format;
88                     config->channel_mask = originalConfig.channel_mask;
89                     config->sample_rate = originalConfig.sample_rate;
90                 }
91             } else {
92                 ALOGE("ERROR - openOutputStream(), SPDIFEncoder does not support format 0x%08x",
93                     originalConfig.format);
94             }
95         }
96     }
97 
98     *ppStreamOut = outputStream;
99     return status;
100 }
101 
openInputStream(AudioStreamIn ** ppStreamIn,audio_io_handle_t handle,audio_devices_t deviceType,audio_input_flags_t flags,struct audio_config * config,const char * address,audio_source_t source,audio_devices_t outputDevice,const char * outputDeviceAddress)102 status_t AudioHwDevice::openInputStream(
103         AudioStreamIn **ppStreamIn,
104         audio_io_handle_t handle,
105         audio_devices_t deviceType,
106         audio_input_flags_t flags,
107         struct audio_config *config,
108         const char *address,
109         audio_source_t source,
110         audio_devices_t outputDevice,
111         const char *outputDeviceAddress) {
112 
113     struct audio_config originalConfig = *config;
114     auto inputStream = new AudioStreamIn(this, flags);
115 
116     // Try to open the HAL first using the current format.
117     ALOGV("openInputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
118             config->format, config->channel_mask);
119     status_t status = inputStream->open(handle, deviceType, config, address, source, outputDevice,
120                                         outputDeviceAddress);
121 
122     // If the input could not be opened with the requested parameters and we can handle the
123     // conversion internally, try to open again with the proposed parameters.
124     if (status == BAD_VALUE &&
125         audio_is_linear_pcm(originalConfig.format) &&
126         audio_is_linear_pcm(config->format) &&
127         (config->sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
128         (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT) &&
129         (audio_channel_count_from_in_mask(originalConfig.channel_mask) <= FCC_LIMIT)) {
130         // FIXME describe the change proposed by HAL (save old values so we can log them here)
131         ALOGV("openInputStream() reopening with proposed sampling rate and channel mask");
132         status = inputStream->open(handle, deviceType, config, address, source,
133                 outputDevice, outputDeviceAddress);
134         // FIXME log this new status; HAL should not propose any further changes
135         if (status != NO_ERROR) {
136             delete inputStream;
137             inputStream = nullptr;
138         }
139     } else if (status != NO_ERROR) {
140         delete inputStream;
141         inputStream = nullptr;
142 
143         // FIXME Look at any modification to the config.
144         // The HAL might modify the config to suggest a wrapped format.
145         // Log this so we can see what the HALs are doing.
146         ALOGI("openInputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
147                 " status %d", config->sample_rate, config->format, config->channel_mask, status);
148 
149         // If the data is encoded then try again using wrapped PCM.
150         const bool unwrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
151                 && ((flags & AUDIO_INPUT_FLAG_DIRECT) != 0);
152 
153         if (unwrapperNeeded) {
154             if (SPDIFDecoder::isFormatSupported(originalConfig.format)) {
155                 inputStream = new SpdifStreamIn(this, flags, originalConfig.format);
156                 status = inputStream->open(handle, deviceType, &originalConfig, address, source,
157                         outputDevice, outputDeviceAddress);
158                 if (status != NO_ERROR) {
159                     ALOGE("ERROR - openInputStream(), SPDIF open returned %d",
160                         status);
161                     delete inputStream;
162                     inputStream = nullptr;
163                 } else {
164                     // on success, we need to assign the actual HAL stream config so that clients
165                     // know and can later patch correctly.
166                     config->format = originalConfig.format;
167                     config->channel_mask = originalConfig.channel_mask;
168                     config->sample_rate = originalConfig.sample_rate;
169                 }
170             } else {
171                 ALOGE("ERROR - openInputStream(), SPDIFDecoder does not support format 0x%08x",
172                     originalConfig.format);
173             }
174         }
175     }
176 
177     *ppStreamIn = inputStream;
178     return status;
179 }
180 
supportsAudioPatches() const181 bool AudioHwDevice::supportsAudioPatches() const {
182     bool result;
183     return mHwDevice->supportsAudioPatches(&result) == OK ? result : false;
184 }
185 
getAudioPort(struct audio_port_v7 * port) const186 status_t AudioHwDevice::getAudioPort(struct audio_port_v7 *port) const {
187     return mHwDevice->getAudioPort(port);
188 }
189 
getMmapPolicyInfos(AudioMMapPolicyType policyType,std::vector<AudioMMapPolicyInfo> * policyInfos) const190 status_t AudioHwDevice::getMmapPolicyInfos(
191             AudioMMapPolicyType policyType, std::vector<AudioMMapPolicyInfo> *policyInfos) const {
192     return mHwDevice->getMmapPolicyInfos(policyType, policyInfos);
193 }
194 
getAAudioMixerBurstCount() const195 int32_t AudioHwDevice::getAAudioMixerBurstCount() const {
196     return mHwDevice->getAAudioMixerBurstCount();
197 }
198 
getAAudioHardwareBurstMinUsec() const199 int32_t AudioHwDevice::getAAudioHardwareBurstMinUsec() const {
200     return mHwDevice->getAAudioHardwareBurstMinUsec();
201 }
202 
getAudioMixPort(const struct audio_port_v7 * devicePort,struct audio_port_v7 * mixPort) const203 status_t AudioHwDevice::getAudioMixPort(const struct audio_port_v7 *devicePort,
204                                         struct audio_port_v7 *mixPort) const {
205     return mHwDevice->getAudioMixPort(devicePort, mixPort);
206 }
207 
208 
209 }; // namespace android
210