blob: 7e095f1499f7a0130cb90e3eca952c455ebe0422 [file] [log] [blame]
Yixiao Luoce501332022-08-12 11:18:18 -07001/*
2 * Copyright 2022 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
Yixiao Luocbb24682023-12-14 11:43:22 -080017#define LOG_TAG "tv_input_aidl_hal_test"
18
Yixiao Luoce501332022-08-12 11:18:18 -070019#include "VtsHalTvInputTargetTest.h"
20
21#include <android-base/properties.h>
22#include <android/binder_ibinder.h>
23#include <android/binder_process.h>
24#include <android/binder_status.h>
25
26using namespace VtsHalTvInputTargetTest;
27
28TvInputAidlTest::TvInputCallback::TvInputCallback(shared_ptr<TvInputAidlTest> parent)
29 : parent_(parent) {}
30
31::ndk::ScopedAStatus TvInputAidlTest::TvInputCallback::notify(const TvInputEvent& in_event) {
32 unique_lock<mutex> lock(parent_->mutex_);
33
34 switch (in_event.type) {
35 case TvInputEventType::DEVICE_AVAILABLE:
36 parent_->onDeviceAvailable(in_event.deviceInfo);
37 break;
38 case TvInputEventType::DEVICE_UNAVAILABLE:
39 parent_->onDeviceUnavailable(in_event.deviceInfo.deviceId);
40 break;
41 case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED:
42 parent_->onStreamConfigurationsChanged(in_event.deviceInfo.deviceId);
43 break;
44 }
45 return ::ndk::ScopedAStatus::ok();
46}
47
David Zhao6bdbc5e2023-01-12 16:51:03 -080048::ndk::ScopedAStatus TvInputAidlTest::TvInputCallback::notifyTvMessageEvent(
49 const TvMessageEvent& in_event) {
50 return ::ndk::ScopedAStatus::ok();
51}
52
Yixiao Luoce501332022-08-12 11:18:18 -070053void TvInputAidlTest::SetUp() {
54 if (AServiceManager_isDeclared(GetParam().c_str())) {
55 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
56 tv_input_ = ITvInput::fromBinder(binder);
57 } else {
58 tv_input_ = nullptr;
59 }
60 ASSERT_NE(tv_input_, nullptr);
61
62 tv_input_callback_ =
63 ::ndk::SharedRefBase::make<TvInputCallback>(shared_ptr<TvInputAidlTest>(this));
64 ASSERT_NE(tv_input_callback_, nullptr);
65
66 tv_input_->setCallback(tv_input_callback_);
67 // All events received within the timeout should be handled.
68 sleep(WAIT_FOR_EVENT_TIMEOUT);
69}
70
71void TvInputAidlTest::TearDown() {
72 tv_input_ = nullptr;
73}
74
75void TvInputAidlTest::onDeviceAvailable(const TvInputDeviceInfo& deviceInfo) {
76 ALOGD("onDeviceAvailable for device id %d", deviceInfo.deviceId);
77 device_info_.add(deviceInfo.deviceId, deviceInfo);
78}
79
80void TvInputAidlTest::onDeviceUnavailable(int32_t deviceId) {
81 ALOGD("onDeviceUnavailable for device id %d", deviceId);
82 device_info_.removeItem(deviceId);
83 stream_config_.removeItem(deviceId);
84}
85
86::ndk::ScopedAStatus TvInputAidlTest::onStreamConfigurationsChanged(int32_t deviceId) {
87 ALOGD("onStreamConfigurationsChanged for device id %d", deviceId);
88 return updateStreamConfigurations(deviceId);
89}
90
91::ndk::ScopedAStatus TvInputAidlTest::updateStreamConfigurations(int32_t deviceId) {
92 stream_config_.removeItem(deviceId);
93 vector<TvStreamConfig> list;
94 ::ndk::ScopedAStatus status = tv_input_->getStreamConfigurations(deviceId, &list);
95 if (status.isOk()) {
96 stream_config_.add(deviceId, list);
97 }
98 return status;
99}
100
101void TvInputAidlTest::updateAllStreamConfigurations() {
102 for (size_t i = 0; i < device_info_.size(); i++) {
103 int32_t device_id = device_info_.keyAt(i);
104 updateStreamConfigurations(device_id);
105 }
106}
107
108vector<size_t> TvInputAidlTest::getConfigIndices() {
109 vector<size_t> indices;
110 for (size_t i = 0; i < stream_config_.size(); i++) {
111 if (stream_config_.valueAt(i).size() != 0) {
112 indices.push_back(i);
113 }
114 }
115 return indices;
116}
117
118int32_t TvInputAidlTest::getNumNotIn(vector<int32_t>& nums) {
119 int32_t result = DEFAULT_ID;
120 int32_t size = static_cast<int32_t>(nums.size());
121 for (int32_t i = 0; i < size; i++) {
122 // Put every element to its target position, if possible.
123 int32_t target_pos = nums[i];
124 while (target_pos >= 0 && target_pos < size && i != target_pos &&
125 nums[i] != nums[target_pos]) {
126 swap(nums[i], nums[target_pos]);
127 target_pos = nums[i];
128 }
129 }
130
131 for (int32_t i = 0; i < size; i++) {
132 if (nums[i] != i) {
133 return i;
134 }
135 }
136 return result;
137}
138
Yixiao Luod6976522023-05-26 15:24:03 -0700139bool TvInputAidlTest::isValidHandle(NativeHandle& handle) {
140 if (handle.fds.empty()) {
141 return false;
142 }
143 for (size_t i = 0; i < handle.fds.size(); i++) {
144 int fd = handle.fds[i].get();
145 if (fcntl(fd, F_GETFL) < 0) {
146 return false;
147 }
148 }
149 return true;
150}
151
Yixiao Luoce501332022-08-12 11:18:18 -0700152/*
153 * GetStreamConfigTest:
154 * Calls updateStreamConfigurations() for each existing device
155 * Checks returned results
156 */
157TEST_P(TvInputAidlTest, GetStreamConfigTest) {
158 unique_lock<mutex> lock(mutex_);
159
160 for (size_t i = 0; i < device_info_.size(); i++) {
161 int32_t device_id = device_info_.keyAt(i);
162 ALOGD("GetStreamConfigTest: device_id=%d", device_id);
163 ASSERT_TRUE(updateStreamConfigurations(device_id).isOk());
164 }
165}
166
167/*
168 * OpenAndCloseStreamTest:
169 * Calls openStream() and then closeStream() for each existing stream
170 * Checks returned results
171 */
172TEST_P(TvInputAidlTest, OpenAndCloseStreamTest) {
173 unique_lock<mutex> lock(mutex_);
174
175 updateAllStreamConfigurations();
176
177 for (size_t j = 0; j < stream_config_.size(); j++) {
178 int32_t device_id = stream_config_.keyAt(j);
179 vector<TvStreamConfig> config = stream_config_.valueAt(j);
180 for (size_t i = 0; i < config.size(); i++) {
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700181 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700182 int32_t stream_id = config[i].streamId;
183 ALOGD("OpenAndCloseStreamTest: open stream, device_id=%d, stream_id=%d", device_id,
184 stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700185 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
Yixiao Luocbb24682023-12-14 11:43:22 -0800186 if (VERIFY_SIDEBAND_STREAM_HANDLE) {
187 ASSERT_TRUE(isValidHandle(handle));
188 }
Yixiao Luod6976522023-05-26 15:24:03 -0700189
Yixiao Luoce501332022-08-12 11:18:18 -0700190 ALOGD("OpenAndCloseStreamTest: close stream, device_id=%d, stream_id=%d", device_id,
191 stream_id);
192 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
193 }
194 }
195}
196
197/*
198 * InvalidDeviceIdTest:
199 * Calls updateStreamConfigurations(), openStream(), and closeStream()
200 * for a non-existing device
201 * Checks returned results
202 * The results should be ITvInput::STATUS_INVALID_ARGUMENTS
203 */
204TEST_P(TvInputAidlTest, InvalidDeviceIdTest) {
205 unique_lock<mutex> lock(mutex_);
206
207 vector<int32_t> device_ids;
208 for (size_t i = 0; i < device_info_.size(); i++) {
209 device_ids.push_back(device_info_.keyAt(i));
210 }
211 // Get a non-existing device ID.
212 int32_t id = getNumNotIn(device_ids);
213 ALOGD("InvalidDeviceIdTest: update stream config, device_id=%d", id);
214 ASSERT_TRUE(updateStreamConfigurations(id).getServiceSpecificError() ==
215 ITvInput::STATUS_INVALID_ARGUMENTS);
216
217 int32_t stream_id = 0;
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700218 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700219
220 ALOGD("InvalidDeviceIdTest: open stream, device_id=%d, stream_id=%d", id, stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700221 ASSERT_TRUE(tv_input_->openStream(id, stream_id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700222 ITvInput::STATUS_INVALID_ARGUMENTS);
223
224 ALOGD("InvalidDeviceIdTest: close stream, device_id=%d, stream_id=%d", id, stream_id);
225 ASSERT_TRUE(tv_input_->closeStream(id, stream_id).getServiceSpecificError() ==
226 ITvInput::STATUS_INVALID_ARGUMENTS);
227}
228
229/*
230 * InvalidStreamIdTest:
231 * Calls openStream(), and closeStream() for a non-existing stream
232 * Checks returned results
233 * The results should be ITvInput::STATUS_INVALID_ARGUMENTS
234 */
235TEST_P(TvInputAidlTest, InvalidStreamIdTest) {
236 unique_lock<mutex> lock(mutex_);
237
238 if (device_info_.isEmpty()) {
239 return;
240 }
241 updateAllStreamConfigurations();
242
243 int32_t device_id = device_info_.keyAt(0);
244 // Get a non-existing stream ID.
245 int32_t id = DEFAULT_ID;
246 if (stream_config_.indexOfKey(device_id) >= 0) {
247 vector<int32_t> stream_ids;
248 vector<TvStreamConfig> config = stream_config_.valueFor(device_id);
249 for (size_t i = 0; i < config.size(); i++) {
250 stream_ids.push_back(config[i].streamId);
251 }
252 id = getNumNotIn(stream_ids);
253 }
254
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700255 NativeHandle handle;
256
Yixiao Luoce501332022-08-12 11:18:18 -0700257 ALOGD("InvalidStreamIdTest: open stream, device_id=%d, stream_id=%d", device_id, id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700258 ASSERT_TRUE(tv_input_->openStream(device_id, id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700259 ITvInput::STATUS_INVALID_ARGUMENTS);
260
261 ALOGD("InvalidStreamIdTest: close stream, device_id=%d, stream_id=%d", device_id, id);
262 ASSERT_TRUE(tv_input_->closeStream(device_id, id).getServiceSpecificError() ==
263 ITvInput::STATUS_INVALID_ARGUMENTS);
264}
265
266/*
267 * OpenAnOpenedStreamsTest:
268 * Calls openStream() twice for a stream (if any)
269 * Checks returned results
270 * The result of the second call should be ITvInput::STATUS_INVALID_STATE
271 */
272TEST_P(TvInputAidlTest, OpenAnOpenedStreamsTest) {
273 unique_lock<mutex> lock(mutex_);
274
275 updateAllStreamConfigurations();
276 vector<size_t> indices = getConfigIndices();
277 if (indices.empty()) {
278 return;
279 }
280 int32_t device_id = stream_config_.keyAt(indices[0]);
David Zhao17a91902023-05-17 16:36:38 -0700281 vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
282 if (streamConfigs.empty()) {
283 return;
284 }
285 int32_t stream_id = streamConfigs[0].streamId;
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700286 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700287
288 ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700289 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
Yixiao Luocbb24682023-12-14 11:43:22 -0800290 if (VERIFY_SIDEBAND_STREAM_HANDLE) {
291 ASSERT_TRUE(isValidHandle(handle));
292 }
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700293
294 ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
295 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700296 ITvInput::STATUS_INVALID_STATE);
297
298 // close stream as subsequent tests assume no open streams
299 ALOGD("OpenAnOpenedStreamsTest: close stream, device_id=%d, stream_id=%d", device_id,
300 stream_id);
301 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
302}
303
304/*
305 * CloseStreamBeforeOpenTest:
306 * Calls closeStream() without calling openStream() for a stream (if any)
307 * Checks the returned result
308 * The result should be ITvInput::STATUS_INVALID_STATE
309 */
310TEST_P(TvInputAidlTest, CloseStreamBeforeOpenTest) {
311 unique_lock<mutex> lock(mutex_);
312
313 updateAllStreamConfigurations();
314 vector<size_t> indices = getConfigIndices();
315 if (indices.empty()) {
316 return;
317 }
318 int32_t device_id = stream_config_.keyAt(indices[0]);
David Zhao17a91902023-05-17 16:36:38 -0700319 vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
320 if (streamConfigs.empty()) {
321 return;
322 }
323 int32_t stream_id = streamConfigs[0].streamId;
Yixiao Luoce501332022-08-12 11:18:18 -0700324
325 ALOGD("CloseStreamBeforeOpenTest: close stream, device_id=%d, stream_id=%d", device_id,
326 stream_id);
327 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).getServiceSpecificError() ==
328 ITvInput::STATUS_INVALID_STATE);
329}
330
David Zhao17a91902023-05-17 16:36:38 -0700331TEST_P(TvInputAidlTest, SetTvMessageEnabledTest) {
332 unique_lock<mutex> lock(mutex_);
333
334 updateAllStreamConfigurations();
335 vector<size_t> indices = getConfigIndices();
336 if (indices.empty()) {
337 return;
338 }
339 int32_t device_id = stream_config_.keyAt(indices[0]);
340 vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
341 if (streamConfigs.empty()) {
342 return;
343 }
344 int32_t stream_id = streamConfigs[0].streamId;
345 ALOGD("SetTvMessageEnabledTest: device_id=%d, stream_id=%d", device_id, stream_id);
346 tv_input_->setTvMessageEnabled(device_id, stream_id, TvMessageEventType::WATERMARK, true);
347}
348
349TEST_P(TvInputAidlTest, GetTvMessageQueueTest) {
350 unique_lock<mutex> lock(mutex_);
351
352 updateAllStreamConfigurations();
353 vector<size_t> indices = getConfigIndices();
354 if (indices.empty()) {
355 return;
356 }
357 int32_t device_id = stream_config_.keyAt(indices[0]);
358 vector<TvStreamConfig> streamConfigs = stream_config_.valueAt(indices[0]);
359 if (streamConfigs.empty()) {
360 return;
361 }
362 int32_t stream_id = streamConfigs[0].streamId;
363 ALOGD("GetTvMessageQueueTest: device_id=%d, stream_id=%d", device_id, stream_id);
David Zhao0dc2bc62023-10-17 11:56:52 -0700364 MQDescriptor<int8_t, SynchronizedReadWrite> queueDescriptor;
365 AidlMessageQueue<int8_t, SynchronizedReadWrite>* queue;
366 tv_input_->getTvMessageQueueDesc(&queueDescriptor, device_id, stream_id);
367 queue = new (std::nothrow) AidlMessageQueue<int8_t, SynchronizedReadWrite>(queueDescriptor);
368 ASSERT_TRUE(queue->isValid());
369 delete queue;
David Zhao17a91902023-05-17 16:36:38 -0700370}
371
Yixiao Luoce501332022-08-12 11:18:18 -0700372INSTANTIATE_TEST_SUITE_P(PerInstance, TvInputAidlTest,
373 testing::ValuesIn(android::getAidlHalInstanceNames(ITvInput::descriptor)),
374 android::PrintInstanceNameToString);
375
376// TODO remove from the allow list once the cf tv target is enabled for testing
377GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TvInputAidlTest);