blob: b072d8fbb71996b1298a068b21e6edf47d348636 [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
17#include "VtsHalTvInputTargetTest.h"
18
19#include <android-base/properties.h>
20#include <android/binder_ibinder.h>
21#include <android/binder_process.h>
22#include <android/binder_status.h>
23
24using namespace VtsHalTvInputTargetTest;
25
26TvInputAidlTest::TvInputCallback::TvInputCallback(shared_ptr<TvInputAidlTest> parent)
27 : parent_(parent) {}
28
29::ndk::ScopedAStatus TvInputAidlTest::TvInputCallback::notify(const TvInputEvent& in_event) {
30 unique_lock<mutex> lock(parent_->mutex_);
31
32 switch (in_event.type) {
33 case TvInputEventType::DEVICE_AVAILABLE:
34 parent_->onDeviceAvailable(in_event.deviceInfo);
35 break;
36 case TvInputEventType::DEVICE_UNAVAILABLE:
37 parent_->onDeviceUnavailable(in_event.deviceInfo.deviceId);
38 break;
39 case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED:
40 parent_->onStreamConfigurationsChanged(in_event.deviceInfo.deviceId);
41 break;
42 }
43 return ::ndk::ScopedAStatus::ok();
44}
45
46void TvInputAidlTest::SetUp() {
47 if (AServiceManager_isDeclared(GetParam().c_str())) {
48 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
49 tv_input_ = ITvInput::fromBinder(binder);
50 } else {
51 tv_input_ = nullptr;
52 }
53 ASSERT_NE(tv_input_, nullptr);
54
55 tv_input_callback_ =
56 ::ndk::SharedRefBase::make<TvInputCallback>(shared_ptr<TvInputAidlTest>(this));
57 ASSERT_NE(tv_input_callback_, nullptr);
58
59 tv_input_->setCallback(tv_input_callback_);
60 // All events received within the timeout should be handled.
61 sleep(WAIT_FOR_EVENT_TIMEOUT);
62}
63
64void TvInputAidlTest::TearDown() {
65 tv_input_ = nullptr;
66}
67
68void TvInputAidlTest::onDeviceAvailable(const TvInputDeviceInfo& deviceInfo) {
69 ALOGD("onDeviceAvailable for device id %d", deviceInfo.deviceId);
70 device_info_.add(deviceInfo.deviceId, deviceInfo);
71}
72
73void TvInputAidlTest::onDeviceUnavailable(int32_t deviceId) {
74 ALOGD("onDeviceUnavailable for device id %d", deviceId);
75 device_info_.removeItem(deviceId);
76 stream_config_.removeItem(deviceId);
77}
78
79::ndk::ScopedAStatus TvInputAidlTest::onStreamConfigurationsChanged(int32_t deviceId) {
80 ALOGD("onStreamConfigurationsChanged for device id %d", deviceId);
81 return updateStreamConfigurations(deviceId);
82}
83
84::ndk::ScopedAStatus TvInputAidlTest::updateStreamConfigurations(int32_t deviceId) {
85 stream_config_.removeItem(deviceId);
86 vector<TvStreamConfig> list;
87 ::ndk::ScopedAStatus status = tv_input_->getStreamConfigurations(deviceId, &list);
88 if (status.isOk()) {
89 stream_config_.add(deviceId, list);
90 }
91 return status;
92}
93
94void TvInputAidlTest::updateAllStreamConfigurations() {
95 for (size_t i = 0; i < device_info_.size(); i++) {
96 int32_t device_id = device_info_.keyAt(i);
97 updateStreamConfigurations(device_id);
98 }
99}
100
101vector<size_t> TvInputAidlTest::getConfigIndices() {
102 vector<size_t> indices;
103 for (size_t i = 0; i < stream_config_.size(); i++) {
104 if (stream_config_.valueAt(i).size() != 0) {
105 indices.push_back(i);
106 }
107 }
108 return indices;
109}
110
111int32_t TvInputAidlTest::getNumNotIn(vector<int32_t>& nums) {
112 int32_t result = DEFAULT_ID;
113 int32_t size = static_cast<int32_t>(nums.size());
114 for (int32_t i = 0; i < size; i++) {
115 // Put every element to its target position, if possible.
116 int32_t target_pos = nums[i];
117 while (target_pos >= 0 && target_pos < size && i != target_pos &&
118 nums[i] != nums[target_pos]) {
119 swap(nums[i], nums[target_pos]);
120 target_pos = nums[i];
121 }
122 }
123
124 for (int32_t i = 0; i < size; i++) {
125 if (nums[i] != i) {
126 return i;
127 }
128 }
129 return result;
130}
131
132/*
133 * GetStreamConfigTest:
134 * Calls updateStreamConfigurations() for each existing device
135 * Checks returned results
136 */
137TEST_P(TvInputAidlTest, GetStreamConfigTest) {
138 unique_lock<mutex> lock(mutex_);
139
140 for (size_t i = 0; i < device_info_.size(); i++) {
141 int32_t device_id = device_info_.keyAt(i);
142 ALOGD("GetStreamConfigTest: device_id=%d", device_id);
143 ASSERT_TRUE(updateStreamConfigurations(device_id).isOk());
144 }
145}
146
147/*
148 * OpenAndCloseStreamTest:
149 * Calls openStream() and then closeStream() for each existing stream
150 * Checks returned results
151 */
152TEST_P(TvInputAidlTest, OpenAndCloseStreamTest) {
153 unique_lock<mutex> lock(mutex_);
154
155 updateAllStreamConfigurations();
156
157 for (size_t j = 0; j < stream_config_.size(); j++) {
158 int32_t device_id = stream_config_.keyAt(j);
159 vector<TvStreamConfig> config = stream_config_.valueAt(j);
160 for (size_t i = 0; i < config.size(); i++) {
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700161 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700162 int32_t stream_id = config[i].streamId;
163 ALOGD("OpenAndCloseStreamTest: open stream, device_id=%d, stream_id=%d", device_id,
164 stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700165 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
Yixiao Luoce501332022-08-12 11:18:18 -0700166 ALOGD("OpenAndCloseStreamTest: close stream, device_id=%d, stream_id=%d", device_id,
167 stream_id);
168 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
169 }
170 }
171}
172
173/*
174 * InvalidDeviceIdTest:
175 * Calls updateStreamConfigurations(), openStream(), and closeStream()
176 * for a non-existing device
177 * Checks returned results
178 * The results should be ITvInput::STATUS_INVALID_ARGUMENTS
179 */
180TEST_P(TvInputAidlTest, InvalidDeviceIdTest) {
181 unique_lock<mutex> lock(mutex_);
182
183 vector<int32_t> device_ids;
184 for (size_t i = 0; i < device_info_.size(); i++) {
185 device_ids.push_back(device_info_.keyAt(i));
186 }
187 // Get a non-existing device ID.
188 int32_t id = getNumNotIn(device_ids);
189 ALOGD("InvalidDeviceIdTest: update stream config, device_id=%d", id);
190 ASSERT_TRUE(updateStreamConfigurations(id).getServiceSpecificError() ==
191 ITvInput::STATUS_INVALID_ARGUMENTS);
192
193 int32_t stream_id = 0;
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700194 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700195
196 ALOGD("InvalidDeviceIdTest: open stream, device_id=%d, stream_id=%d", id, stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700197 ASSERT_TRUE(tv_input_->openStream(id, stream_id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700198 ITvInput::STATUS_INVALID_ARGUMENTS);
199
200 ALOGD("InvalidDeviceIdTest: close stream, device_id=%d, stream_id=%d", id, stream_id);
201 ASSERT_TRUE(tv_input_->closeStream(id, stream_id).getServiceSpecificError() ==
202 ITvInput::STATUS_INVALID_ARGUMENTS);
203}
204
205/*
206 * InvalidStreamIdTest:
207 * Calls openStream(), and closeStream() for a non-existing stream
208 * Checks returned results
209 * The results should be ITvInput::STATUS_INVALID_ARGUMENTS
210 */
211TEST_P(TvInputAidlTest, InvalidStreamIdTest) {
212 unique_lock<mutex> lock(mutex_);
213
214 if (device_info_.isEmpty()) {
215 return;
216 }
217 updateAllStreamConfigurations();
218
219 int32_t device_id = device_info_.keyAt(0);
220 // Get a non-existing stream ID.
221 int32_t id = DEFAULT_ID;
222 if (stream_config_.indexOfKey(device_id) >= 0) {
223 vector<int32_t> stream_ids;
224 vector<TvStreamConfig> config = stream_config_.valueFor(device_id);
225 for (size_t i = 0; i < config.size(); i++) {
226 stream_ids.push_back(config[i].streamId);
227 }
228 id = getNumNotIn(stream_ids);
229 }
230
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700231 NativeHandle handle;
232
Yixiao Luoce501332022-08-12 11:18:18 -0700233 ALOGD("InvalidStreamIdTest: open stream, device_id=%d, stream_id=%d", device_id, id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700234 ASSERT_TRUE(tv_input_->openStream(device_id, id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700235 ITvInput::STATUS_INVALID_ARGUMENTS);
236
237 ALOGD("InvalidStreamIdTest: close stream, device_id=%d, stream_id=%d", device_id, id);
238 ASSERT_TRUE(tv_input_->closeStream(device_id, id).getServiceSpecificError() ==
239 ITvInput::STATUS_INVALID_ARGUMENTS);
240}
241
242/*
243 * OpenAnOpenedStreamsTest:
244 * Calls openStream() twice for a stream (if any)
245 * Checks returned results
246 * The result of the second call should be ITvInput::STATUS_INVALID_STATE
247 */
248TEST_P(TvInputAidlTest, OpenAnOpenedStreamsTest) {
249 unique_lock<mutex> lock(mutex_);
250
251 updateAllStreamConfigurations();
252 vector<size_t> indices = getConfigIndices();
253 if (indices.empty()) {
254 return;
255 }
256 int32_t device_id = stream_config_.keyAt(indices[0]);
257 int32_t stream_id = stream_config_.valueAt(indices[0])[0].streamId;
258
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700259 NativeHandle handle;
Yixiao Luoce501332022-08-12 11:18:18 -0700260
261 ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
Yixiao Luo4cd52a92022-10-28 15:51:48 -0700262 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).isOk());
263
264 ALOGD("OpenAnOpenedStreamsTest: open stream, device_id=%d, stream_id=%d", device_id, stream_id);
265 ASSERT_TRUE(tv_input_->openStream(device_id, stream_id, &handle).getServiceSpecificError() ==
Yixiao Luoce501332022-08-12 11:18:18 -0700266 ITvInput::STATUS_INVALID_STATE);
267
268 // close stream as subsequent tests assume no open streams
269 ALOGD("OpenAnOpenedStreamsTest: close stream, device_id=%d, stream_id=%d", device_id,
270 stream_id);
271 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).isOk());
272}
273
274/*
275 * CloseStreamBeforeOpenTest:
276 * Calls closeStream() without calling openStream() for a stream (if any)
277 * Checks the returned result
278 * The result should be ITvInput::STATUS_INVALID_STATE
279 */
280TEST_P(TvInputAidlTest, CloseStreamBeforeOpenTest) {
281 unique_lock<mutex> lock(mutex_);
282
283 updateAllStreamConfigurations();
284 vector<size_t> indices = getConfigIndices();
285 if (indices.empty()) {
286 return;
287 }
288 int32_t device_id = stream_config_.keyAt(indices[0]);
289 int32_t stream_id = stream_config_.valueAt(indices[0])[0].streamId;
290
291 ALOGD("CloseStreamBeforeOpenTest: close stream, device_id=%d, stream_id=%d", device_id,
292 stream_id);
293 ASSERT_TRUE(tv_input_->closeStream(device_id, stream_id).getServiceSpecificError() ==
294 ITvInput::STATUS_INVALID_STATE);
295}
296
297INSTANTIATE_TEST_SUITE_P(PerInstance, TvInputAidlTest,
298 testing::ValuesIn(android::getAidlHalInstanceNames(ITvInput::descriptor)),
299 android::PrintInstanceNameToString);
300
301// TODO remove from the allow list once the cf tv target is enabled for testing
302GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TvInputAidlTest);