1 /*
2 * Copyright (C) 2018 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 #define LOG_NDEBUG 0
18 #define LOG_TAG "codec2_hidl_hal_component_test"
19
20 #include <android-base/logging.h>
21 #include <gtest/gtest.h>
22
23 #include <hardware/google/media/c2/1.0/IComponent.h>
24 #include <hardware/google/media/c2/1.0/IComponentStore.h>
25
26 using ::hardware::google::media::c2::V1_0::IComponent;
27 using ::hardware::google::media::c2::V1_0::IComponentStore;
28 using ::hardware::google::media::c2::V1_0::IComponentInterface;
29 using ::hardware::google::media::c2::V1_0::FieldSupportedValuesQuery;
30 using ::hardware::google::media::c2::V1_0::FieldSupportedValuesQueryResult;
31 using ::hardware::google::media::c2::V1_0::ParamDescriptor;
32 using ::hardware::google::media::c2::V1_0::SettingResult;
33 using ::android::hardware::hidl_vec;
34 using ::android::hardware::hidl_string;
35 using ::android::sp;
36
37 #include <VtsHalHidlTargetTestBase.h>
38 #include "media_c2_hidl_test_common.h"
39
40 static ComponentTestEnvironment* gEnv = nullptr;
41
42 namespace {
43
44 // google.codec2 Component test setup
45 class Codec2ComponentHalTest : public ::testing::VtsHalHidlTargetTestBase {
46 private:
47 typedef ::testing::VtsHalHidlTargetTestBase Super;
48
49 public:
SetUp()50 virtual void SetUp() override {
51 Super::SetUp();
52 mStore = Super::getService<IComponentStore>(gEnv->getInstance());
53 ASSERT_NE(mStore, nullptr);
54 mListener = new CodecListener();
55 ASSERT_NE(mListener, nullptr);
56 mStore->createComponent(gEnv->getComponent().c_str(), mListener,
57 nullptr,
58 [&](Status _s, const sp<IComponent>& _nl) {
59 ASSERT_EQ(_s, Status::OK);
60 this->mComponent = _nl;
61 });
62 ASSERT_NE(mComponent, nullptr);
63 }
64
TearDown()65 virtual void TearDown() override {
66 if (mComponent != nullptr) {
67 // If you have encountered a fatal failure, it is possible that
68 // freeNode() will not go through. Instead of hanging the app.
69 // let it pass through and report errors
70 if (::testing::Test::HasFatalFailure()) return;
71 mComponent->release();
72 mComponent = nullptr;
73 }
74 Super::TearDown();
75 }
76
77 sp<IComponent> mComponent;
78 sp<IComponentStore> mStore;
79 sp<CodecListener> mListener;
80
81 protected:
description(const std::string & description)82 static void description(const std::string& description) {
83 RecordProperty("description", description);
84 }
85 };
86
87 // Test Empty Flush
TEST_F(Codec2ComponentHalTest,EmptyFlush)88 TEST_F(Codec2ComponentHalTest, EmptyFlush) {
89 ALOGV("Empty Flush Test");
90 Status err = mComponent->start();
91 ASSERT_EQ(err, Status::OK);
92
93 // Flushed output expected to be of 0 size, as no input has been fed
94 mComponent->flush([&](Status _s, const WorkBundle& _flushedWorkBundle) {
95 ASSERT_EQ(_s, Status::OK);
96 ASSERT_EQ(_flushedWorkBundle.works.size(), 0u)
97 << "Invalid Flushed Work Size";
98 ASSERT_EQ(_flushedWorkBundle.baseBlocks.size(), 0u);
99 });
100 }
101
102 // Test Queue Empty Work
TEST_F(Codec2ComponentHalTest,QueueEmptyWork)103 TEST_F(Codec2ComponentHalTest, QueueEmptyWork) {
104 ALOGV("Queue Empty Work Test");
105 Status err = mComponent->start();
106 ASSERT_EQ(err, Status::OK);
107
108 // Queueing an empty WorkBundle
109 const WorkBundle workBundle = {};
110 err = mComponent->queue(workBundle);
111 ASSERT_EQ(err, Status::OK);
112
113 err = mComponent->reset();
114 ASSERT_EQ(err, Status::OK);
115 }
116
117 // Test Component Configuration
TEST_F(Codec2ComponentHalTest,Config)118 TEST_F(Codec2ComponentHalTest, Config) {
119 ALOGV("Configuration Test");
120 mComponent->getName([](const hidl_string& name) {
121 EXPECT_NE(name.empty(), true) << "Invalid Component Store Name";
122 ALOGV("Component under Test %s", name.c_str());
123 });
124
125 #define MAX_PARAMS 64
126 /* Querry Supported Params */
127 hidl_vec<ParamDescriptor> params;
128 mComponent->querySupportedParams(
129 0, MAX_PARAMS,
130 [¶ms](Status _s, const hidl_vec<ParamDescriptor>& _p) {
131 ASSERT_EQ(_s, Status::OK);
132 params = _p;
133 ALOGE("TEMP - Params capacity - %zu", _p.size());
134 });
135
136 std::vector<uint32_t> tempIndices;
137 std::vector<FieldSupportedValuesQuery> tempInFields;
138 for (size_t i = 0; i < params.size(); i++) {
139 EXPECT_NE(params[i].name.empty(), true)
140 << "Invalid Supported Param Name";
141 ALOGV("Params Supported : %s", params[i].name.c_str());
142 tempIndices.push_back(params[i].index);
143 FieldSupportedValuesQuery tempFSV;
144 tempFSV.field.index = params[i].index;
145 tempInFields.push_back(tempFSV);
146 }
147
148
149 /* Query Supported Values */
150 const hidl_vec<FieldSupportedValuesQuery> inFields = tempInFields;
151 bool mayBlock = false;
152 hidl_vec<FieldSupportedValuesQueryResult> outFields;
153 mComponent->querySupportedValues(
154 inFields, mayBlock,
155 [&outFields](
156 Status _s,
157 const hidl_vec<FieldSupportedValuesQueryResult>& _outFields) {
158 ASSERT_EQ(_s, Status::OK);
159 outFields = _outFields;
160 });
161
162 // Fileds size should match
163 ASSERT_EQ(inFields.size(), outFields.size());
164
165 /* TODO: How to give proper indices */
166 const hidl_vec<uint32_t> indices = tempIndices;
167 hidl_vec<uint8_t> inParamsQuery;
168 mComponent->query(indices, mayBlock,
169 [&inParamsQuery](Status _s, const hidl_vec<uint8_t>& _p) {
170 ASSERT_EQ(_s, Status::OK);
171 inParamsQuery = _p;
172 });
173
174 /* Config default parameters*/
175 const hidl_vec<uint8_t> inParams = inParamsQuery;
176 hidl_vec<uint8_t> outParamsQuery;
177 mComponent->config(
178 inParams, mayBlock,
179 [&outParamsQuery](Status _s, const hidl_vec<SettingResult>& _f,
180 const hidl_vec<uint8_t>& _outParams) {
181 ASSERT_EQ(_s, Status::OK);
182 // There should be no failures, since default config is reapplied
183 ASSERT_EQ(_f.size(), 0u);
184 outParamsQuery = _outParams;
185 });
186
187 // Fileds size should match
188 ASSERT_EQ(inParams.size(), outParamsQuery.size());
189 }
190
191 // Test Multiple Start Stop Reset Test
TEST_F(Codec2ComponentHalTest,MultipleStartStopReset)192 TEST_F(Codec2ComponentHalTest, MultipleStartStopReset) {
193 ALOGV("Multiple Start Stop and Reset Test");
194 Status err = Status::OK;
195
196 #define MAX_RETRY 16
197
198 for (size_t i = 0; i < MAX_RETRY; i++) {
199 err = mComponent->start();
200 ASSERT_EQ(err, Status::OK);
201
202 err = mComponent->stop();
203 ASSERT_EQ(err, Status::OK);
204 }
205
206 err = mComponent->start();
207 ASSERT_EQ(err, Status::OK);
208
209 for (size_t i = 0; i < MAX_RETRY; i++) {
210 err = mComponent->reset();
211 ASSERT_EQ(err, Status::OK);
212 }
213
214 err = mComponent->start();
215 ASSERT_EQ(err, Status::OK);
216
217 err = mComponent->stop();
218 ASSERT_EQ(err, Status::OK);
219
220 // Second stop should return error
221 err = mComponent->stop();
222 ASSERT_NE(err, Status::OK);
223 }
224
225 } // anonymous namespace
226
227 // TODO: Add test for Invalid work, Invalid Config handling
228 // TODO: Add test for Invalid states
main(int argc,char ** argv)229 int main(int argc, char** argv) {
230 gEnv = new ComponentTestEnvironment();
231 ::testing::AddGlobalTestEnvironment(gEnv);
232 ::testing::InitGoogleTest(&argc, argv);
233 gEnv->init(&argc, argv);
234 int status = gEnv->initFromOptions(argc, argv);
235 if (status == 0) {
236 status = RUN_ALL_TESTS();
237 LOG(INFO) << "C2 Test result = " << status;
238 }
239 return status;
240 }
241
242