blob: 002aa699bb9d36ca349362ba53fd840f0e230a7c [file] [log] [blame]
Phil Burk062e67a2015-02-11 13:40:50 -08001/*
Dean Wheatley6c009512023-10-23 09:34:14 +11002 *
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 */
Phil Burk062e67a2015-02-11 13:40:50 -080017
18#define LOG_TAG "AudioHwDevice"
19//#define LOG_NDEBUG 0
20
Mikhail Naganovcbc8f612016-10-11 18:05:13 -070021#include <system/audio.h>
Phil Burk062e67a2015-02-11 13:40:50 -080022#include <utils/Log.h>
23
Dean Wheatley6c009512023-10-23 09:34:14 +110024#include <audio_utils/spdif/SPDIFDecoder.h>
Phil Burk062e67a2015-02-11 13:40:50 -080025#include <audio_utils/spdif/SPDIFEncoder.h>
Dean Wheatley6c009512023-10-23 09:34:14 +110026#include <media/AudioResamplerPublic.h>
Phil Burk062e67a2015-02-11 13:40:50 -080027
28#include "AudioHwDevice.h"
29#include "AudioStreamOut.h"
Dean Wheatley6c009512023-10-23 09:34:14 +110030#include "SpdifStreamIn.h"
Phil Burk062e67a2015-02-11 13:40:50 -080031#include "SpdifStreamOut.h"
32
33namespace android {
34
jiabine99d0882021-09-17 05:21:25 +000035using media::audio::common::AudioMMapPolicyInfo;
36using media::audio::common::AudioMMapPolicyType;
37
Phil Burk062e67a2015-02-11 13:40:50 -080038// ----------------------------------------------------------------------------
39
40status_t AudioHwDevice::openOutputStream(
41 AudioStreamOut **ppStreamOut,
42 audio_io_handle_t handle,
jiabin43810402019-10-24 14:58:31 -070043 audio_devices_t deviceType,
Dean Wheatleydfb67b82024-01-23 09:36:29 +110044 audio_output_flags_t *flags,
Phil Burk062e67a2015-02-11 13:40:50 -080045 struct audio_config *config,
Haofan Wangb75aa6a2024-07-09 23:06:58 -070046 const char *address,
47 const std::vector<playback_track_metadata_v7_t>& sourceMetadata)
Phil Burk062e67a2015-02-11 13:40:50 -080048{
49
50 struct audio_config originalConfig = *config;
Dean Wheatleydfb67b82024-01-23 09:36:29 +110051 auto outputStream = new AudioStreamOut(this);
Phil Burk062e67a2015-02-11 13:40:50 -080052
53 // Try to open the HAL first using the current format.
Dean Wheatley6c009512023-10-23 09:34:14 +110054 ALOGV("openOutputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
55 config->format, config->channel_mask);
Dean Wheatleydfb67b82024-01-23 09:36:29 +110056 status_t status = outputStream->open(handle, deviceType, config, flags, address,
57 sourceMetadata);
Phil Burk062e67a2015-02-11 13:40:50 -080058
59 if (status != NO_ERROR) {
60 delete outputStream;
Andy Hung1ef77382023-06-15 14:50:18 -070061 outputStream = nullptr;
Phil Burk062e67a2015-02-11 13:40:50 -080062
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.
Dean Wheatley6c009512023-10-23 09:34:14 +110066 ALOGI("openOutputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
67 " status %d", config->sample_rate, config->format, config->channel_mask, status);
Phil Burk062e67a2015-02-11 13:40:50 -080068
69 // If the data is encoded then try again using wrapped PCM.
Andy Hung1ef77382023-06-15 14:50:18 -070070 const bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
Dean Wheatleydfb67b82024-01-23 09:36:29 +110071 && ((*flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
72 && ((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);
Phil Burk062e67a2015-02-11 13:40:50 -080073
Phil Burk062e67a2015-02-11 13:40:50 -080074 if (wrapperNeeded) {
Phil Burk23d89972015-04-06 16:22:23 -070075 if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
Dean Wheatleydfb67b82024-01-23 09:36:29 +110076 outputStream = new SpdifStreamOut(this, originalConfig.format);
77 status = outputStream->open(handle, deviceType, &originalConfig, flags, address,
Haofan Wangb75aa6a2024-07-09 23:06:58 -070078 sourceMetadata);
Phil Burk23d89972015-04-06 16:22:23 -070079 if (status != NO_ERROR) {
80 ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
81 status);
82 delete outputStream;
Andy Hung1ef77382023-06-15 14:50:18 -070083 outputStream = nullptr;
Phil Burk23d89972015-04-06 16:22:23 -070084 }
85 } else {
86 ALOGE("ERROR - openOutputStream(), SPDIFEncoder does not support format 0x%08x",
87 originalConfig.format);
Phil Burk062e67a2015-02-11 13:40:50 -080088 }
89 }
90 }
91
92 *ppStreamOut = outputStream;
93 return status;
94}
95
Dean Wheatley6c009512023-10-23 09:34:14 +110096status_t AudioHwDevice::openInputStream(
97 AudioStreamIn **ppStreamIn,
98 audio_io_handle_t handle,
99 audio_devices_t deviceType,
100 audio_input_flags_t flags,
101 struct audio_config *config,
102 const char *address,
103 audio_source_t source,
104 audio_devices_t outputDevice,
105 const char *outputDeviceAddress) {
106
107 struct audio_config originalConfig = *config;
108 auto inputStream = new AudioStreamIn(this, flags);
109
110 // Try to open the HAL first using the current format.
111 ALOGV("openInputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
112 config->format, config->channel_mask);
113 status_t status = inputStream->open(handle, deviceType, config, address, source, outputDevice,
114 outputDeviceAddress);
115
116 // If the input could not be opened with the requested parameters and we can handle the
117 // conversion internally, try to open again with the proposed parameters.
118 if (status == BAD_VALUE &&
119 audio_is_linear_pcm(originalConfig.format) &&
120 audio_is_linear_pcm(config->format) &&
121 (config->sample_rate <= AUDIO_RESAMPLER_DOWN_RATIO_MAX * config->sample_rate) &&
122 (audio_channel_count_from_in_mask(config->channel_mask) <= FCC_LIMIT) &&
123 (audio_channel_count_from_in_mask(originalConfig.channel_mask) <= FCC_LIMIT)) {
124 // FIXME describe the change proposed by HAL (save old values so we can log them here)
125 ALOGV("openInputStream() reopening with proposed sampling rate and channel mask");
126 status = inputStream->open(handle, deviceType, config, address, source,
127 outputDevice, outputDeviceAddress);
128 // FIXME log this new status; HAL should not propose any further changes
129 if (status != NO_ERROR) {
130 delete inputStream;
131 inputStream = nullptr;
132 }
133 } else if (status != NO_ERROR) {
134 delete inputStream;
135 inputStream = nullptr;
136
137 // FIXME Look at any modification to the config.
138 // The HAL might modify the config to suggest a wrapped format.
139 // Log this so we can see what the HALs are doing.
140 ALOGI("openInputStream(), HAL returned sampleRate %d, format %#x, channelMask %#x,"
141 " status %d", config->sample_rate, config->format, config->channel_mask, status);
142
143 // If the data is encoded then try again using wrapped PCM.
144 const bool unwrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
145 && ((flags & AUDIO_INPUT_FLAG_DIRECT) != 0);
146
147 if (unwrapperNeeded) {
148 if (SPDIFDecoder::isFormatSupported(originalConfig.format)) {
149 inputStream = new SpdifStreamIn(this, flags, originalConfig.format);
150 status = inputStream->open(handle, deviceType, &originalConfig, address, source,
151 outputDevice, outputDeviceAddress);
152 if (status != NO_ERROR) {
153 ALOGE("ERROR - openInputStream(), SPDIF open returned %d",
154 status);
155 delete inputStream;
156 inputStream = nullptr;
157 }
158 } else {
159 ALOGE("ERROR - openInputStream(), SPDIFDecoder does not support format 0x%08x",
160 originalConfig.format);
161 }
162 }
163 }
164
165 *ppStreamIn = inputStream;
166 return status;
167}
168
Mikhail Naganov9ee05402016-10-13 15:58:17 -0700169bool AudioHwDevice::supportsAudioPatches() const {
170 bool result;
171 return mHwDevice->supportsAudioPatches(&result) == OK ? result : false;
Mikhail Naganove4f1f632016-08-31 11:35:10 -0700172}
Phil Burk062e67a2015-02-11 13:40:50 -0800173
jiabinb4fed192020-09-22 14:45:40 -0700174status_t AudioHwDevice::getAudioPort(struct audio_port_v7 *port) const {
175 return mHwDevice->getAudioPort(port);
176}
177
Jiabin Huangebe64102021-09-07 20:01:07 +0000178status_t AudioHwDevice::getMmapPolicyInfos(
jiabine99d0882021-09-17 05:21:25 +0000179 AudioMMapPolicyType policyType, std::vector<AudioMMapPolicyInfo> *policyInfos) const {
Jiabin Huangebe64102021-09-07 20:01:07 +0000180 return mHwDevice->getMmapPolicyInfos(policyType, policyInfos);
181}
182
jiabine504e7b2021-09-18 00:27:08 +0000183int32_t AudioHwDevice::getAAudioMixerBurstCount() const {
184 return mHwDevice->getAAudioMixerBurstCount();
185}
186
187int32_t AudioHwDevice::getAAudioHardwareBurstMinUsec() const {
188 return mHwDevice->getAAudioHardwareBurstMinUsec();
189}
190
jiabin12537fc2023-10-12 17:56:08 +0000191status_t AudioHwDevice::getAudioMixPort(const struct audio_port_v7 *devicePort,
192 struct audio_port_v7 *mixPort) const {
193 return mHwDevice->getAudioMixPort(devicePort, mixPort);
194}
195
Jiabin Huangebe64102021-09-07 20:01:07 +0000196
Phil Burk062e67a2015-02-11 13:40:50 -0800197}; // namespace android