blob: 56af1528c0448f78a5abb93743f6d7c7b3b445a3 [file] [log] [blame]
Mikhail Naganovad3f8a12017-12-12 13:24:23 -08001/*
2 * Copyright (C) 2017 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
Mikhail Naganov04a86632017-12-15 18:01:42 -080017#include <memory>
18#include <set>
Mikhail Naganov21b43362018-06-04 10:37:09 -070019#include <sys/wait.h>
20#include <unistd.h>
Mikhail Naganov04a86632017-12-15 18:01:42 -080021
Mikhail Naganovad3f8a12017-12-12 13:24:23 -080022#include <gtest/gtest.h>
23
Mikhail Naganov21b43362018-06-04 10:37:09 -070024#define LOG_TAG "APM_Test"
25#include <log/log.h>
Mikhail Naganovdc769682018-05-04 15:34:08 -070026#include <media/PatchBuilder.h>
27
Mikhail Naganovad3f8a12017-12-12 13:24:23 -080028#include "AudioPolicyTestClient.h"
29#include "AudioPolicyTestManager.h"
30
31using namespace android;
32
Mikhail Naganov04a86632017-12-15 18:01:42 -080033TEST(AudioPolicyManagerTestInit, Failure) {
Mikhail Naganovad3f8a12017-12-12 13:24:23 -080034 AudioPolicyTestClient client;
35 AudioPolicyTestManager manager(&client);
36 manager.getConfig().setDefault();
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080037 // Since the default client fails to open anything,
38 // APM should indicate that the initialization didn't succeed.
Mikhail Naganovad3f8a12017-12-12 13:24:23 -080039 ASSERT_EQ(NO_INIT, manager.initialize());
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080040 ASSERT_EQ(NO_INIT, manager.initCheck());
41}
42
43
Mikhail Naganov04a86632017-12-15 18:01:42 -080044class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080045 public:
Mikhail Naganov04a86632017-12-15 18:01:42 -080046 // AudioPolicyClientInterface implementation
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080047 audio_module_handle_t loadHwModule(const char* /*name*/) override {
Mikhail Naganov04a86632017-12-15 18:01:42 -080048 return mNextModuleHandle++;
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080049 }
Mikhail Naganov04a86632017-12-15 18:01:42 -080050
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080051 status_t openOutput(audio_module_handle_t module,
52 audio_io_handle_t* output,
53 audio_config_t* /*config*/,
54 audio_devices_t* /*devices*/,
55 const String8& /*address*/,
56 uint32_t* /*latencyMs*/,
57 audio_output_flags_t /*flags*/) override {
Mikhail Naganov04a86632017-12-15 18:01:42 -080058 if (module >= mNextModuleHandle) {
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080059 ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
Mikhail Naganov04a86632017-12-15 18:01:42 -080060 __func__, module, mNextModuleHandle);
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080061 return BAD_VALUE;
62 }
63 *output = mNextIoHandle++;
64 return NO_ERROR;
65 }
Mikhail Naganov04a86632017-12-15 18:01:42 -080066
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080067 status_t openInput(audio_module_handle_t module,
68 audio_io_handle_t* input,
69 audio_config_t* /*config*/,
70 audio_devices_t* /*device*/,
71 const String8& /*address*/,
72 audio_source_t /*source*/,
73 audio_input_flags_t /*flags*/) override {
Mikhail Naganov04a86632017-12-15 18:01:42 -080074 if (module >= mNextModuleHandle) {
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080075 ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
Mikhail Naganov04a86632017-12-15 18:01:42 -080076 __func__, module, mNextModuleHandle);
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -080077 return BAD_VALUE;
78 }
79 *input = mNextIoHandle++;
80 return NO_ERROR;
81 }
Mikhail Naganov04a86632017-12-15 18:01:42 -080082
83 status_t createAudioPatch(const struct audio_patch* /*patch*/,
84 audio_patch_handle_t* handle,
85 int /*delayMs*/) override {
86 *handle = mNextPatchHandle++;
87 mActivePatches.insert(*handle);
88 return NO_ERROR;
89 }
90
91 status_t releaseAudioPatch(audio_patch_handle_t handle,
92 int /*delayMs*/) override {
93 if (mActivePatches.erase(handle) != 1) {
94 if (handle >= mNextPatchHandle) {
95 ALOGE("%s: Patch handle %d has not been allocated yet (next is %d)",
96 __func__, handle, mNextPatchHandle);
97 } else {
98 ALOGE("%s: Attempt to release patch %d twice", __func__, handle);
99 }
100 return BAD_VALUE;
101 }
102 return NO_ERROR;
103 }
104
105 // Helper methods for tests
106 size_t getActivePatchesCount() const { return mActivePatches.size(); }
107
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -0800108 private:
Mikhail Naganov04a86632017-12-15 18:01:42 -0800109 audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -0800110 audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
Mikhail Naganov04a86632017-12-15 18:01:42 -0800111 audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
112 std::set<audio_patch_handle_t> mActivePatches;
Mikhail Naganovbcbcb1b2017-12-13 13:03:35 -0800113};
114
Mikhail Naganov04a86632017-12-15 18:01:42 -0800115class AudioPolicyManagerTest : public testing::Test {
116 protected:
117 virtual void SetUp();
118 virtual void TearDown();
119
120 std::unique_ptr<AudioPolicyManagerTestClient> mClient;
121 std::unique_ptr<AudioPolicyTestManager> mManager;
122};
123
124void AudioPolicyManagerTest::SetUp() {
125 mClient.reset(new AudioPolicyManagerTestClient);
126 mManager.reset(new AudioPolicyTestManager(mClient.get()));
127 mManager->getConfig().setDefault();
128 ASSERT_EQ(NO_ERROR, mManager->initialize());
129 ASSERT_EQ(NO_ERROR, mManager->initCheck());
Mikhail Naganovad3f8a12017-12-12 13:24:23 -0800130}
Mikhail Naganov04a86632017-12-15 18:01:42 -0800131
132void AudioPolicyManagerTest::TearDown() {
133 mManager.reset();
134 mClient.reset();
135}
136
137TEST_F(AudioPolicyManagerTest, InitSuccess) {
138 // SetUp must finish with no assertions.
139}
140
Mikhail Naganov21b43362018-06-04 10:37:09 -0700141TEST_F(AudioPolicyManagerTest, Dump) {
142 int pipefd[2];
143 ASSERT_NE(-1, pipe(pipefd));
144 pid_t cpid = fork();
145 ASSERT_NE(-1, cpid);
146 if (cpid == 0) {
147 // Child process reads from the pipe and logs.
148 close(pipefd[1]);
149 std::string line;
150 char buf;
151 while (read(pipefd[0], &buf, sizeof(buf)) > 0) {
152 if (buf != '\n') {
153 line += buf;
154 } else {
155 ALOGI("%s", line.c_str());
156 line = "";
157 }
158 }
159 if (!line.empty()) ALOGI("%s", line.c_str());
160 close(pipefd[0]);
161 _exit(EXIT_SUCCESS);
162 } else {
163 // Parent does the dump and checks the status code.
164 close(pipefd[0]);
165 ASSERT_EQ(NO_ERROR, mManager->dump(pipefd[1]));
166 close(pipefd[1]);
167 wait(NULL); // Wait for the child to exit.
168 }
169}
170
Mikhail Naganov04a86632017-12-15 18:01:42 -0800171TEST_F(AudioPolicyManagerTest, CreateAudioPatchFailure) {
172 audio_patch patch{};
173 audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
174 const size_t patchCountBefore = mClient->getActivePatchesCount();
175 ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
176 ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
177 ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
178 patch.num_sources = AUDIO_PATCH_PORTS_MAX + 1;
179 patch.num_sinks = 1;
180 ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
181 patch.num_sources = 1;
182 patch.num_sinks = AUDIO_PATCH_PORTS_MAX + 1;
183 ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
184 patch.num_sources = 2;
185 patch.num_sinks = 1;
186 ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
187 patch = {};
188 patch.num_sources = 1;
189 patch.sources[0].role = AUDIO_PORT_ROLE_SINK;
190 patch.num_sinks = 1;
191 patch.sinks[0].role = AUDIO_PORT_ROLE_SINK;
192 ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
193 patch = {};
194 patch.num_sources = 1;
195 patch.sources[0].role = AUDIO_PORT_ROLE_SOURCE;
196 patch.num_sinks = 1;
197 patch.sinks[0].role = AUDIO_PORT_ROLE_SOURCE;
198 ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
199 // Verify that the handle is left unchanged.
200 ASSERT_EQ(AUDIO_PATCH_HANDLE_NONE, handle);
201 ASSERT_EQ(patchCountBefore, mClient->getActivePatchesCount());
202}
203
204TEST_F(AudioPolicyManagerTest, CreateAudioPatchFromMix) {
Mikhail Naganov04a86632017-12-15 18:01:42 -0800205 audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
206 uid_t uid = 42;
207 const size_t patchCountBefore = mClient->getActivePatchesCount();
Mikhail Naganovdc769682018-05-04 15:34:08 -0700208 ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
209 PatchBuilder patchBuilder;
210 patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
211 addSink(mManager->getConfig().getDefaultOutputDevice());
212 ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
Mikhail Naganov04a86632017-12-15 18:01:42 -0800213 ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
214 ASSERT_EQ(patchCountBefore + 1, mClient->getActivePatchesCount());
215}
216
217// TODO: Add patch creation tests that involve already existing patch