blob: 28a913ccb0516f421e04ae3e1a071f1b39832145 [file] [log] [blame]
Eric Laurent566fcda2016-11-23 10:36:36 -08001/*
2 * Copyright (C) 2016 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_TAG "BroadcastRadioHidlHalTest"
18#include <gtest/gtest.h>
19#include <android-base/logging.h>
20#include <cutils/native_handle.h>
21#include <cutils/properties.h>
Martijn Coenen02822372016-12-29 14:03:41 +010022#include <hidl/HidlTransportSupport.h>
Eric Laurent566fcda2016-11-23 10:36:36 -080023#include <utils/threads.h>
Eric Laurent566fcda2016-11-23 10:36:36 -080024
25#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
26#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
27#include <android/hardware/broadcastradio/1.0/ITuner.h>
28#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
29#include <android/hardware/broadcastradio/1.0/types.h>
30
31
32using ::android::sp;
33using ::android::Mutex;
34using ::android::Condition;
Eric Laurent566fcda2016-11-23 10:36:36 -080035using ::android::hardware::Return;
36using ::android::hardware::Status;
37using ::android::hardware::Void;
38using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
39using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
40using ::android::hardware::broadcastradio::V1_0::ITuner;
41using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
42using ::android::hardware::broadcastradio::V1_0::Result;
43using ::android::hardware::broadcastradio::V1_0::Class;
44using ::android::hardware::broadcastradio::V1_0::Properties;
45using ::android::hardware::broadcastradio::V1_0::BandConfig;
46using ::android::hardware::broadcastradio::V1_0::Direction;
47using ::android::hardware::broadcastradio::V1_0::ProgramInfo;
48using ::android::hardware::broadcastradio::V1_0::MetaData;
49
50
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080051// The main test class for Broadcast Radio HIDL HAL.
Eric Laurent566fcda2016-11-23 10:36:36 -080052
53class BroadcastRadioHidlTest : public ::testing::Test {
54 protected:
55 virtual void SetUp() override {
56 bool getStub = false;
57 char getsubProperty[PROPERTY_VALUE_MAX];
58 if (property_get("vts.hidl.get_stub", getsubProperty, "") > 0) {
59 if (!strcmp(getsubProperty, "true") ||
60 !strcmp(getsubProperty, "True") ||
61 !strcmp(getsubProperty, "1")) {
62 getStub = true;
63 }
64 }
65 sp<IBroadcastRadioFactory> factory =
Chris Phoenixf6090102017-01-25 14:10:31 -080066 IBroadcastRadioFactory::getService(getStub);
Eric Laurent566fcda2016-11-23 10:36:36 -080067 if (factory != 0) {
68 factory->connectModule(Class::AM_FM,
69 [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
70 if (retval == Result::OK) {
71 mRadio = result;
72 }
73 });
74 }
75 mTunerCallback = new MyCallback(this);
76 ASSERT_NE(nullptr, mRadio.get());
77 ASSERT_EQ(!getStub, mRadio->isRemote());
78 ASSERT_NE(nullptr, mTunerCallback.get());
79 }
80
81 virtual void TearDown() override {
82 mTuner.clear();
83 mRadio.clear();
84 }
85
86 class MyCallback : public ITunerCallback {
87 public:
88
89 // ITunerCallback methods (see doc in ITunerCallback.hal)
90 virtual Return<void> hardwareFailure() {
91 ALOGI("%s", __FUNCTION__);
92 mParentTest->onHwFailureCallback();
93 return Void();
94 }
95
96 virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
97 ALOGI("%s result %d", __FUNCTION__, result);
98 mParentTest->onResultCallback(result);
99 return Void();
100 }
101
102 virtual Return<void> tuneComplete(Result result, const ProgramInfo& info __unused) {
103 ALOGI("%s result %d", __FUNCTION__, result);
104 mParentTest->onResultCallback(result);
105 return Void();
106 }
107
108 virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
109 return Void();
110 }
111
112 virtual Return<void> antennaStateChange(bool connected) {
113 ALOGI("%s connected %d", __FUNCTION__, connected);
114 return Void();
115 }
116
117 virtual Return<void> trafficAnnouncement(bool active) {
118 ALOGI("%s active %d", __FUNCTION__, active);
119 return Void();
120 }
121
122 virtual Return<void> emergencyAnnouncement(bool active) {
123 ALOGI("%s active %d", __FUNCTION__, active);
124 return Void();
125 }
126
127 virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
128 const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
129 ALOGI("%s", __FUNCTION__);
130 return Void();
131 }
132
133 MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
134
135 private:
136 // BroadcastRadioHidlTest instance to which callbacks will be notified.
137 BroadcastRadioHidlTest *mParentTest;
138 };
139
140
141 /**
142 * Method called by MyCallback when a callback with no status or boolean value is received
143 */
144 void onCallback() {
145 Mutex::Autolock _l(mLock);
146 onCallback_l();
147 }
148
149 /**
150 * Method called by MyCallback when hardwareFailure() callback is received
151 */
152 void onHwFailureCallback() {
153 Mutex::Autolock _l(mLock);
154 mHwFailure = true;
155 onCallback_l();
156 }
157
158 /**
159 * Method called by MyCallback when a callback with status is received
160 */
161 void onResultCallback(Result result) {
162 Mutex::Autolock _l(mLock);
163 mResultCallbackData = result;
164 onCallback_l();
165 }
166
167 /**
168 * Method called by MyCallback when a boolean indication is received
169 */
170 void onBoolCallback(bool result) {
171 Mutex::Autolock _l(mLock);
172 mBoolCallbackData = result;
173 onCallback_l();
174 }
175
176
177 BroadcastRadioHidlTest() :
178 mCallbackCalled(false), mBoolCallbackData(false),
179 mResultCallbackData(Result::OK), mHwFailure(false) {}
180
181 void onCallback_l() {
182 if (!mCallbackCalled) {
183 mCallbackCalled = true;
184 mCallbackCond.broadcast();
185 }
186 }
187
188
189 bool waitForCallback(nsecs_t reltime = 0) {
190 Mutex::Autolock _l(mLock);
191 nsecs_t endTime = systemTime() + reltime;
192 while (!mCallbackCalled) {
193 if (reltime == 0) {
194 mCallbackCond.wait(mLock);
195 } else {
196 nsecs_t now = systemTime();
197 if (now > endTime) {
198 return false;
199 }
200 mCallbackCond.waitRelative(mLock, endTime - now);
201 }
202 }
203 return true;
204 }
205
206 bool getProperties();
207 bool openTuner();
208 bool checkAntenna();
209
210 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
211 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
212
213 sp<IBroadcastRadio> mRadio;
214 Properties mHalProperties;
215 sp<ITuner> mTuner;
216 sp<MyCallback> mTunerCallback;
217 Mutex mLock;
218 Condition mCallbackCond;
219 bool mCallbackCalled;
220 bool mBoolCallbackData;
221 Result mResultCallbackData;
222 bool mHwFailure;
223};
224
225// A class for test environment setup (kept since this file is a template).
226class BroadcastRadioHidlEnvironment : public ::testing::Environment {
227 public:
228 virtual void SetUp() {}
229 virtual void TearDown() {}
230};
231
232bool BroadcastRadioHidlTest::getProperties()
233{
234 if (mHalProperties.bands.size() == 0) {
235 Result halResult = Result::NOT_INITIALIZED;
236 Return<void> hidlReturn =
237 mRadio->getProperties([&](Result result, const Properties& properties) {
238 halResult = result;
239 if (result == Result::OK) {
240 mHalProperties = properties;
241 }
242 });
243
Steven Morelandb6438422017-01-03 17:06:57 -0800244 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800245 EXPECT_EQ(Result::OK, halResult);
246 EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
247 EXPECT_GT(mHalProperties.numTuners, 0u);
248 EXPECT_GT(mHalProperties.bands.size(), 0u);
249 }
250 return mHalProperties.bands.size() > 0;
251}
252
253bool BroadcastRadioHidlTest::openTuner()
254{
255 if (!getProperties()) {
256 return false;
257 }
258 if (mTuner.get() == nullptr) {
259 Result halResult = Result::NOT_INITIALIZED;
260 Return<void> hidlReturn =
261 mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
262 [&](Result result, const sp<ITuner>& tuner) {
263 halResult = result;
264 if (result == Result::OK) {
265 mTuner = tuner;
266 }
267 });
Steven Morelandb6438422017-01-03 17:06:57 -0800268 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800269 EXPECT_EQ(Result::OK, halResult);
270 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
271 }
272 EXPECT_NE(nullptr, mTuner.get());
273 return nullptr != mTuner.get();
274}
275
276bool BroadcastRadioHidlTest::checkAntenna()
277{
278 BandConfig halConfig;
279 Result halResult = Result::NOT_INITIALIZED;
280 Return<void> hidlReturn =
281 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
282 halResult = result;
283 if (result == Result::OK) {
284 halConfig = config;
285 }
286 });
287
288 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
289}
290
291
292/**
293 * Test IBroadcastRadio::getProperties() method
294 *
295 * Verifies that:
296 * - the HAL implements the method
297 * - the method returns 0 (no error)
298 * - the implementation class is AM_FM
299 * - the implementation supports at least one tuner
300 * - the implementation supports at one band
301 */
302TEST_F(BroadcastRadioHidlTest, GetProperties) {
303 EXPECT_EQ(true, getProperties());
304}
305
306/**
307 * Test IBroadcastRadio::openTuner() method
308 *
309 * Verifies that:
310 * - the HAL implements the method
311 * - the method returns 0 (no error) and a valid ITuner interface
312 */
313TEST_F(BroadcastRadioHidlTest, OpenTuner) {
314 EXPECT_EQ(true, openTuner());
315}
316
317/**
318 * Test ITuner::setConfiguration() and getConfiguration methods
319 *
320 * Verifies that:
321 * - the HAL implements both methods
322 * - the methods return 0 (no error)
323 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
324 * - the configuration read back from HAl has the same class Id
325 */
326TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
327 ASSERT_EQ(true, openTuner());
328 // test setConfiguration
329 mCallbackCalled = false;
330 Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
Steven Morelandb6438422017-01-03 17:06:57 -0800331 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800332 EXPECT_EQ(Result::OK, hidlResult);
333 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
334 EXPECT_EQ(Result::OK, mResultCallbackData);
335
336 // test getConfiguration
337 BandConfig halConfig;
338 Result halResult;
339 Return<void> hidlReturn =
340 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
341 halResult = result;
342 if (result == Result::OK) {
343 halConfig = config;
344 }
345 });
Steven Morelandb6438422017-01-03 17:06:57 -0800346 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800347 EXPECT_EQ(Result::OK, halResult);
348 EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
349}
350
351/**
352 * Test ITuner::scan
353 *
354 * Verifies that:
355 * - the HAL implements the method
356 * - the method returns 0 (no error)
357 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
358 */
359TEST_F(BroadcastRadioHidlTest, Scan) {
360 ASSERT_EQ(true, openTuner());
361 ASSERT_TRUE(checkAntenna());
362 // test scan UP
363 mCallbackCalled = false;
364 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800365 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800366 EXPECT_EQ(Result::OK, hidlResult);
367 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
368
369 // test scan DOWN
370 mCallbackCalled = false;
371 hidlResult = mTuner->scan(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800372 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800373 EXPECT_EQ(Result::OK, hidlResult);
374 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
375}
376
377/**
378 * Test ITuner::step
379 *
380 * Verifies that:
381 * - the HAL implements the method
382 * - the method returns 0 (no error)
383 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
384 */
385TEST_F(BroadcastRadioHidlTest, Step) {
386 ASSERT_EQ(true, openTuner());
387 ASSERT_TRUE(checkAntenna());
388 // test step UP
389 mCallbackCalled = false;
390 Return<Result> hidlResult = mTuner->step(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800391 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800392 EXPECT_EQ(Result::OK, hidlResult);
393 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
394
395 // test step DOWN
396 mCallbackCalled = false;
397 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800398 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800399 EXPECT_EQ(Result::OK, hidlResult);
400 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
401}
402
403/**
404 * Test ITuner::tune, getProgramInformation and cancel methods
405 *
406 * Verifies that:
407 * - the HAL implements the methods
408 * - the methods return 0 (no error)
409 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
410 */
411TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
412 ASSERT_EQ(true, openTuner());
413 ASSERT_TRUE(checkAntenna());
414
415 // test tune
416 ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
417 ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
418
419 // test scan UP
420 uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
421 uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
422 uint32_t spacing = mHalProperties.bands[0].spacings[0];
423
424 uint32_t channel =
425 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
426 mCallbackCalled = false;
427 mResultCallbackData = Result::NOT_INITIALIZED;
428 Return<Result> hidlResult = mTuner->tune(channel, 0);
Steven Morelandb6438422017-01-03 17:06:57 -0800429 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800430 EXPECT_EQ(Result::OK, hidlResult);
431 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
432
433 // test getProgramInformation
434 ProgramInfo halInfo;
435 Result halResult = Result::NOT_INITIALIZED;
436 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800437 [&](Result result, const ProgramInfo& info) {
438 halResult = result;
439 if (result == Result::OK) {
440 halInfo = info;
441 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800442 });
Steven Morelandb6438422017-01-03 17:06:57 -0800443 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800444 EXPECT_EQ(Result::OK, halResult);
445 if (mResultCallbackData == Result::OK) {
446 EXPECT_EQ(true, halInfo.tuned);
447 EXPECT_LE(halInfo.channel, upperLimit);
448 EXPECT_GE(halInfo.channel, lowerLimit);
449 } else {
450 EXPECT_EQ(false, halInfo.tuned);
451 }
452
453 // test cancel
454 mTuner->tune(lowerLimit, 0);
455 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800456 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800457 EXPECT_EQ(Result::OK, hidlResult);
458}
459
460
461int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800462 ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
463 ::testing::InitGoogleTest(&argc, argv);
464 int status = RUN_ALL_TESTS();
465 ALOGI("Test result = %d", status);
466 return status;
467}