blob: ca7ad40827047d3d45dd9646d7bd06372c507639 [file] [log] [blame]
jiabin38b2c5d2019-09-26 17:56:44 -07001/*
2 * Copyright (C) 2019 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#include <map>
Mikhail Naganov21762fa2020-03-05 16:28:57 -080018#include <set>
jiabin38b2c5d2019-09-26 17:56:44 -070019
Mikhail Naganov285c1732024-09-05 17:26:50 -070020#include <media/TypeConverter.h>
jiabin38b2c5d2019-09-26 17:56:44 -070021#include <system/audio.h>
22#include <utils/Log.h>
23#include <utils/String8.h>
24
25#include "AudioPolicyTestClient.h"
26
27namespace android {
28
29class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
30public:
31 // AudioPolicyClientInterface implementation
Mikhail Naganov21762fa2020-03-05 16:28:57 -080032 audio_module_handle_t loadHwModule(const char* name) override {
33 if (!mAllowedModuleNames.empty() && !mAllowedModuleNames.count(name)) {
34 return AUDIO_MODULE_HANDLE_NONE;
35 }
jiabin38b2c5d2019-09-26 17:56:44 -070036 return mNextModuleHandle++;
37 }
38
39 status_t openOutput(audio_module_handle_t module,
40 audio_io_handle_t *output,
Mikhail Naganov285c1732024-09-05 17:26:50 -070041 audio_config_t *halConfig,
42 audio_config_base_t *mixerConfig,
jiabinc0106832019-10-24 14:58:31 -070043 const sp<DeviceDescriptorBase>& /*device*/,
jiabin38b2c5d2019-09-26 17:56:44 -070044 uint32_t * /*latencyMs*/,
Mikhail Naganov285c1732024-09-05 17:26:50 -070045 audio_output_flags_t flags,
Haofan Wangb75aa6a2024-07-09 23:06:58 -070046 audio_attributes_t /*attributes*/) override {
jiabin38b2c5d2019-09-26 17:56:44 -070047 if (module >= mNextModuleHandle) {
48 ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
49 __func__, module, mNextModuleHandle);
50 return BAD_VALUE;
51 }
52 *output = mNextIoHandle++;
Mikhail Naganov285c1732024-09-05 17:26:50 -070053 mOpenedOutputs[*output] = flags;
54 ALOGD("%s: opened output %d: HAL(%s %s %d) Mixer(%s %s %d) %s", __func__, *output,
55 audio_channel_out_mask_to_string(halConfig->channel_mask),
56 audio_format_to_string(halConfig->format), halConfig->sample_rate,
57 audio_channel_out_mask_to_string(mixerConfig->channel_mask),
58 audio_format_to_string(mixerConfig->format), mixerConfig->sample_rate,
59 android::toString(flags).c_str());
jiabin38b2c5d2019-09-26 17:56:44 -070060 return NO_ERROR;
61 }
62
63 audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
64 audio_io_handle_t /*output2*/) override {
65 audio_io_handle_t id = mNextIoHandle++;
66 return id;
67 }
68
Mikhail Naganov285c1732024-09-05 17:26:50 -070069 status_t closeOutput(audio_io_handle_t output) override {
70 if (auto iter = mOpenedOutputs.find(output); iter != mOpenedOutputs.end()) {
71 mOpenedOutputs.erase(iter);
72 return NO_ERROR;
73 } else {
74 ALOGE("%s: Unknown output %d", __func__, output);
75 return BAD_VALUE;
76 }
77 }
78
jiabin38b2c5d2019-09-26 17:56:44 -070079 status_t openInput(audio_module_handle_t module,
80 audio_io_handle_t *input,
81 audio_config_t * /*config*/,
82 audio_devices_t * /*device*/,
83 const String8 & /*address*/,
84 audio_source_t /*source*/,
85 audio_input_flags_t /*flags*/) override {
86 if (module >= mNextModuleHandle) {
87 ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
88 __func__, module, mNextModuleHandle);
89 return BAD_VALUE;
90 }
91 *input = mNextIoHandle++;
Mikhail Naganovc66ffc12024-05-30 16:56:25 -070092 mOpenedInputs.insert(*input);
93 ALOGD("%s: opened input %d", __func__, *input);
94 return NO_ERROR;
95 }
96
97 status_t closeInput(audio_io_handle_t input) override {
98 if (mOpenedInputs.erase(input) != 1) {
99 if (input >= mNextIoHandle) {
100 ALOGE("%s: I/O handle %d has not been allocated yet (next is %d)",
101 __func__, input, mNextIoHandle);
102 } else {
103 ALOGE("%s: Attempt to close input %d twice", __func__, input);
104 }
105 return BAD_VALUE;
106 }
107 ALOGD("%s: closed input %d", __func__, input);
jiabin38b2c5d2019-09-26 17:56:44 -0700108 return NO_ERROR;
109 }
110
111 status_t createAudioPatch(const struct audio_patch *patch,
112 audio_patch_handle_t *handle,
113 int /*delayMs*/) override {
Dean Wheatley514b4312020-06-17 21:45:00 +1000114 auto iter = mActivePatches.find(*handle);
115 if (iter != mActivePatches.end()) {
116 mActivePatches.erase(*handle);
117 }
jiabin38b2c5d2019-09-26 17:56:44 -0700118 *handle = mNextPatchHandle++;
119 mActivePatches.insert(std::make_pair(*handle, *patch));
120 return NO_ERROR;
121 }
122
123 status_t releaseAudioPatch(audio_patch_handle_t handle,
124 int /*delayMs*/) override {
125 if (mActivePatches.erase(handle) != 1) {
126 if (handle >= mNextPatchHandle) {
127 ALOGE("%s: Patch handle %d has not been allocated yet (next is %d)",
128 __func__, handle, mNextPatchHandle);
129 } else {
130 ALOGE("%s: Attempt to release patch %d twice", __func__, handle);
131 }
132 return BAD_VALUE;
133 }
134 return NO_ERROR;
135 }
136
Mikhail Naganova30ec142020-03-24 09:32:34 -0700137 void onAudioPortListUpdate() override {
138 ++mAudioPortListUpdateCount;
139 }
140
jiabinc0048632023-04-27 22:04:31 +0000141 status_t setDeviceConnectedState(const struct audio_port_v7 *port,
142 media::DeviceConnectedState state) override {
143 if (state == media::DeviceConnectedState::CONNECTED) {
Mikhail Naganovddc5f312022-06-11 00:47:52 +0000144 mConnectedDevicePorts.push_back(*port);
jiabinc0048632023-04-27 22:04:31 +0000145 } else if (state == media::DeviceConnectedState::DISCONNECTED){
Mikhail Naganovddc5f312022-06-11 00:47:52 +0000146 mDisconnectedDevicePorts.push_back(*port);
147 }
Mikhail Naganov516d3982022-02-01 23:53:59 +0000148 return NO_ERROR;
149 }
150
jiabin38b2c5d2019-09-26 17:56:44 -0700151 // Helper methods for tests
152 size_t getActivePatchesCount() const { return mActivePatches.size(); }
153
154 const struct audio_patch *getLastAddedPatch() const {
155 if (mActivePatches.empty()) {
156 return nullptr;
157 }
158 auto it = --mActivePatches.end();
159 return &it->second;
160 };
161
Mikhail Naganovc66ffc12024-05-30 16:56:25 -0700162 size_t getOpenedInputsCount() const { return mOpenedInputs.size(); }
163
Mikhail Naganov21762fa2020-03-05 16:28:57 -0800164 audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }
165
166 void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
167 mAllowedModuleNames.swap(names);
168 }
169
Mikhail Naganova30ec142020-03-24 09:32:34 -0700170 size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
171
Jean-Michel Trivi9a6b9ad2020-10-22 16:46:43 -0700172 void onRoutingUpdated() override {
173 mRoutingUpdatedUpdateCount++;
174 }
175
176 void resetRoutingUpdatedCounter() {
177 mRoutingUpdatedUpdateCount = 0;
178 }
179
180 size_t getRoutingUpdatedCounter() const {
Jean-Michel Trivi78f2b302022-04-15 18:18:41 +0000181 return mRoutingUpdatedUpdateCount;
182 }
183
184 void onVolumeRangeInitRequest() override {
185
186 }
Jean-Michel Trivi9a6b9ad2020-10-22 16:46:43 -0700187
jiabinf042b9b2021-05-07 23:46:28 +0000188 status_t updateSecondaryOutputs(
189 const TrackSecondaryOutputsMap& trackSecondaryOutputs __unused) override {
190 return NO_ERROR;
191 }
192
Mikhail Naganovddc5f312022-06-11 00:47:52 +0000193 size_t getConnectedDevicePortCount() const {
194 return mConnectedDevicePorts.size();
195 }
196
197 const struct audio_port_v7 *getLastConnectedDevicePort() const {
198 if (mConnectedDevicePorts.empty()) {
199 return nullptr;
200 }
201 auto it = --mConnectedDevicePorts.end();
202 return &(*it);
203 }
204
205 size_t getDisconnectedDevicePortCount() const {
206 return mDisconnectedDevicePorts.size();
207 }
208
209 const struct audio_port_v7 *getLastDisconnectedDevicePort() const {
210 if (mDisconnectedDevicePorts.empty()) {
211 return nullptr;
212 }
213 auto it = --mDisconnectedDevicePorts.end();
214 return &(*it);
215 }
216
jiabina84c3d32022-12-02 18:59:55 +0000217 String8 getParameters(audio_io_handle_t /* ioHandle */, const String8& /* keys*/ ) override {
218 AudioParameter mAudioParameters;
219 std::string formats;
220 for (const auto& f : mSupportedFormats) {
221 if (!formats.empty()) formats += AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
222 formats += audio_format_to_string(f);
223 }
224 mAudioParameters.add(
225 String8(AudioParameter::keyStreamSupportedFormats),
226 String8(formats.c_str()));
227 mAudioParameters.addInt(String8(AudioParameter::keyStreamSupportedSamplingRates), 48000);
228 std::string channelMasks;
229 for (const auto& cm : mSupportedChannelMasks) {
jiabin3ff8d7d2022-12-13 06:27:44 +0000230 if (!audio_channel_mask_is_valid(cm)) {
jiabina84c3d32022-12-02 18:59:55 +0000231 continue;
232 }
233 if (!channelMasks.empty()) channelMasks += AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
234 channelMasks += audio_channel_mask_to_string(cm);
235 }
236 mAudioParameters.add(
237 String8(AudioParameter::keyStreamSupportedChannels), String8(channelMasks.c_str()));
238 return mAudioParameters.toString();
239 }
240
jiabin12537fc2023-10-12 17:56:08 +0000241 status_t getAudioMixPort(const struct audio_port_v7 *devicePort __unused,
242 struct audio_port_v7 *mixPort) override {
243 mixPort->num_audio_profiles = 0;
244 for (auto format : mSupportedFormats) {
245 const int i = mixPort->num_audio_profiles;
246 mixPort->audio_profiles[i].format = format;
247 mixPort->audio_profiles[i].num_sample_rates = 1;
248 mixPort->audio_profiles[i].sample_rates[0] = 48000;
249 mixPort->audio_profiles[i].num_channel_masks = 0;
250 for (const auto& cm : mSupportedChannelMasks) {
251 if (audio_channel_mask_is_valid(cm)) {
252 mixPort->audio_profiles[i].channel_masks[
253 mixPort->audio_profiles[i].num_channel_masks++] = cm;
254 }
255 }
256 mixPort->num_audio_profiles++;
257 }
258 return NO_ERROR;
259 }
260
jiabin220eea12024-05-17 17:55:20 +0000261 status_t setTracksInternalMute(
262 const std::vector<media::TrackInternalMuteInfo>& tracksInternalMute) override {
263 for (const auto& trackInternalMute : tracksInternalMute) {
264 mTracksInternalMute[(audio_port_handle_t)trackInternalMute.portId] =
265 trackInternalMute.muted;
266 }
267 return NO_ERROR;
268 }
269
jiabina84c3d32022-12-02 18:59:55 +0000270 void addSupportedFormat(audio_format_t format) {
271 mSupportedFormats.insert(format);
272 }
273
274 void addSupportedChannelMask(audio_channel_mask_t channelMask) {
275 mSupportedChannelMasks.insert(channelMask);
276 }
277
jiabin220eea12024-05-17 17:55:20 +0000278 bool getTrackInternalMute(audio_port_handle_t portId) {
279 auto it = mTracksInternalMute.find(portId);
280 return it == mTracksInternalMute.end() ? false : it->second;
281 }
282
Mikhail Naganov285c1732024-09-05 17:26:50 -0700283 std::optional<audio_output_flags_t> getOpenOutputFlags(audio_io_handle_t output) const {
284 if (auto iter = mOpenedOutputs.find(output); iter != mOpenedOutputs.end()) {
285 return iter->second;
286 }
287 return std::nullopt;
288 }
289
jiabin38b2c5d2019-09-26 17:56:44 -0700290private:
291 audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
292 audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
293 audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
294 std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
Mikhail Naganov21762fa2020-03-05 16:28:57 -0800295 std::set<std::string> mAllowedModuleNames;
Mikhail Naganova30ec142020-03-24 09:32:34 -0700296 size_t mAudioPortListUpdateCount = 0;
Jean-Michel Trivi9a6b9ad2020-10-22 16:46:43 -0700297 size_t mRoutingUpdatedUpdateCount = 0;
Mikhail Naganovddc5f312022-06-11 00:47:52 +0000298 std::vector<struct audio_port_v7> mConnectedDevicePorts;
299 std::vector<struct audio_port_v7> mDisconnectedDevicePorts;
jiabina84c3d32022-12-02 18:59:55 +0000300 std::set<audio_format_t> mSupportedFormats;
301 std::set<audio_channel_mask_t> mSupportedChannelMasks;
jiabin220eea12024-05-17 17:55:20 +0000302 std::map<audio_port_handle_t, bool> mTracksInternalMute;
Mikhail Naganovc66ffc12024-05-30 16:56:25 -0700303 std::set<audio_io_handle_t> mOpenedInputs;
Mikhail Naganov285c1732024-09-05 17:26:50 -0700304 std::map<audio_io_handle_t, audio_output_flags_t> mOpenedOutputs;
jiabin38b2c5d2019-09-26 17:56:44 -0700305};
306
307} // namespace android