2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "BroadcastRadioHidlHalTest"
18 #include <VtsHalHidlTargetTestBase.h>
19 #include <android-base/logging.h>
20 #include <cutils/native_handle.h>
21 #include <cutils/properties.h>
22 #include <hidl/HidlTransportSupport.h>
23 #include <utils/threads.h>
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>
33 using ::android::Mutex;
34 using ::android::Condition;
35 using ::android::hardware::Return;
36 using ::android::hardware::Void;
37 using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
38 using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
39 using ::android::hardware::broadcastradio::V1_0::ITuner;
40 using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
41 using ::android::hardware::broadcastradio::V1_0::Result;
42 using ::android::hardware::broadcastradio::V1_0::Class;
43 using ::android::hardware::broadcastradio::V1_0::Properties;
44 using ::android::hardware::broadcastradio::V1_0::Band;
45 using ::android::hardware::broadcastradio::V1_0::BandConfig;
46 using ::android::hardware::broadcastradio::V1_0::Direction;
47 using ::android::hardware::broadcastradio::V1_0::ProgramInfo;
48 using ::android::hardware::broadcastradio::V1_0::MetaData;
51 #define RETURN_IF_SKIPPED \
53 std::cout << "[ SKIPPED ] This device class is not supported. " << std::endl; \
57 // The main test class for Broadcast Radio HIDL HAL.
59 class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
60 public ::testing::WithParamInterface<Class> {
62 virtual void SetUp() override {
63 ASSERT_EQ(nullptr, mRadio.get());
65 radioClass = GetParam();
68 sp<IBroadcastRadioFactory> factory =
69 ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
70 ASSERT_NE(nullptr, factory.get());
73 factory->connectModule(radioClass, [&](Result ret, const sp<IBroadcastRadio>& radio) {
78 EXPECT_EQ(true, waitForCallback(kConnectCallbacktimeoutNs));
79 mCallbackCalled = false;
81 if (connectResult == Result::INVALID_ARGUMENTS) {
85 ASSERT_EQ(connectResult, Result::OK);
87 mTunerCallback = new MyCallback(this);
88 ASSERT_NE(nullptr, mRadio.get());
89 ASSERT_NE(nullptr, mTunerCallback.get());
92 virtual void TearDown() override {
97 class MyCallback : public ITunerCallback {
100 // ITunerCallback methods (see doc in ITunerCallback.hal)
101 virtual Return<void> hardwareFailure() {
102 ALOGI("%s", __FUNCTION__);
103 mParentTest->onHwFailureCallback();
107 virtual Return<void> configChange(Result result, const BandConfig& config) {
108 ALOGI("%s result %d", __FUNCTION__, result);
109 mParentTest->onConfigChangeCallback(result, config);
113 virtual Return<void> tuneComplete(Result result, const ProgramInfo& info) {
114 ALOGI("%s result %d", __FUNCTION__, result);
115 mParentTest->onTuneCompleteCallback(result, info);
119 virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
123 virtual Return<void> antennaStateChange(bool connected) {
124 ALOGI("%s connected %d", __FUNCTION__, connected);
128 virtual Return<void> trafficAnnouncement(bool active) {
129 ALOGI("%s active %d", __FUNCTION__, active);
133 virtual Return<void> emergencyAnnouncement(bool active) {
134 ALOGI("%s active %d", __FUNCTION__, active);
138 virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
139 const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
140 ALOGI("%s", __FUNCTION__);
144 MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
147 // BroadcastRadioHidlTest instance to which callbacks will be notified.
148 BroadcastRadioHidlTest *mParentTest;
153 * Method called by MyCallback when a callback with no status or boolean value is received
156 Mutex::Autolock _l(mLock);
161 * Method called by MyCallback when hardwareFailure() callback is received
163 void onHwFailureCallback() {
164 Mutex::Autolock _l(mLock);
170 * Method called by MyCallback when configChange() callback is received.
172 void onConfigChangeCallback(Result result, const BandConfig& config) {
173 Mutex::Autolock _l(mLock);
174 mResultCallbackData = result;
175 mBandConfigCallbackData = config;
180 * Method called by MyCallback when tuneComplete() callback is received.
182 void onTuneCompleteCallback(Result result, const ProgramInfo& info) {
183 Mutex::Autolock _l(mLock);
184 mResultCallbackData = result;
185 mProgramInfoCallbackData = info;
190 * Method called by MyCallback when a boolean indication is received
192 void onBoolCallback(bool result) {
193 Mutex::Autolock _l(mLock);
194 mBoolCallbackData = result;
199 BroadcastRadioHidlTest()
200 : mCallbackCalled(false), mBoolCallbackData(false), mResultCallbackData(Result::OK),
203 void onCallback_l() {
204 if (!mCallbackCalled) {
205 mCallbackCalled = true;
206 mCallbackCond.broadcast();
211 bool waitForCallback(nsecs_t reltime = 0) {
212 Mutex::Autolock _l(mLock);
213 nsecs_t endTime = systemTime() + reltime;
214 while (!mCallbackCalled) {
216 mCallbackCond.wait(mLock);
218 nsecs_t now = systemTime();
222 mCallbackCond.waitRelative(mLock, endTime - now);
228 bool getProperties();
232 static const nsecs_t kConnectCallbacktimeoutNs = seconds_to_nanoseconds(1);
233 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
234 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
238 sp<IBroadcastRadio> mRadio;
239 Properties mHalProperties;
241 sp<MyCallback> mTunerCallback;
243 Condition mCallbackCond;
244 bool mCallbackCalled;
245 bool mBoolCallbackData;
246 Result mResultCallbackData;
247 ProgramInfo mProgramInfoCallbackData;
248 BandConfig mBandConfigCallbackData;
254 namespace broadcastradio {
258 * Compares two BandConfig objects for testing purposes.
260 static bool operator==(const BandConfig& l, const BandConfig& r) {
261 if (l.type != r.type) return false;
262 if (l.antennaConnected != r.antennaConnected) return false;
263 if (l.lowerLimit != r.lowerLimit) return false;
264 if (l.upperLimit != r.upperLimit) return false;
265 if (l.spacings != r.spacings) return false;
266 if (l.type == Band::AM || l.type == Band::AM_HD) {
267 return l.ext.am == r.ext.am;
268 } else if (l.type == Band::FM || l.type == Band::FM_HD) {
269 return l.ext.fm == r.ext.fm;
281 bool BroadcastRadioHidlTest::getProperties()
283 if (mHalProperties.bands.size() == 0) {
284 Result halResult = Result::NOT_INITIALIZED;
285 Return<void> hidlReturn =
286 mRadio->getProperties([&](Result result, const Properties& properties) {
288 if (result == Result::OK) {
289 mHalProperties = properties;
293 EXPECT_TRUE(hidlReturn.isOk());
294 EXPECT_EQ(Result::OK, halResult);
295 EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
296 EXPECT_GT(mHalProperties.numTuners, 0u);
297 EXPECT_GT(mHalProperties.bands.size(), 0u);
299 return mHalProperties.bands.size() > 0;
302 bool BroadcastRadioHidlTest::openTuner()
304 if (!getProperties()) {
307 if (mTuner.get() == nullptr) {
308 Result halResult = Result::NOT_INITIALIZED;
309 Return<void> hidlReturn =
310 mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
311 [&](Result result, const sp<ITuner>& tuner) {
313 if (result == Result::OK) {
317 EXPECT_TRUE(hidlReturn.isOk());
318 EXPECT_EQ(Result::OK, halResult);
319 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
321 EXPECT_NE(nullptr, mTuner.get());
322 return nullptr != mTuner.get();
325 bool BroadcastRadioHidlTest::checkAntenna()
327 BandConfig halConfig;
328 Result halResult = Result::NOT_INITIALIZED;
329 Return<void> hidlReturn =
330 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
332 if (result == Result::OK) {
337 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
342 * Test IBroadcastRadio::getProperties() method
345 * - the HAL implements the method
346 * - the method returns 0 (no error)
347 * - the implementation class is AM_FM
348 * - the implementation supports at least one tuner
349 * - the implementation supports at one band
351 TEST_P(BroadcastRadioHidlTest, GetProperties) {
353 EXPECT_EQ(true, getProperties());
357 * Test IBroadcastRadio::openTuner() method
360 * - the HAL implements the method
361 * - the method returns 0 (no error) and a valid ITuner interface
363 TEST_P(BroadcastRadioHidlTest, OpenTuner) {
365 EXPECT_EQ(true, openTuner());
369 * Test IBroadcastRadio::openTuner() after ITuner disposal.
372 * - ITuner destruction gets propagated through HAL
373 * - the openTuner method works well when called for the second time
375 TEST_P(BroadcastRadioHidlTest, ReopenTuner) {
377 EXPECT_TRUE(openTuner());
379 EXPECT_TRUE(openTuner());
383 * Test IBroadcastRadio::openTuner() method called twice.
386 * - the openTuner method fails when called for the second time without deleting previous
389 TEST_P(BroadcastRadioHidlTest, OpenTunerTwice) {
391 EXPECT_TRUE(openTuner());
393 Result halResult = Result::NOT_INITIALIZED;
394 Return<void> hidlReturn =
395 mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
396 [&](Result result, const sp<ITuner>&) {
399 EXPECT_TRUE(hidlReturn.isOk());
400 EXPECT_EQ(Result::INVALID_STATE, halResult);
401 EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
405 * Test ITuner::setConfiguration() and getConfiguration methods
408 * - the HAL implements both methods
409 * - the methods return 0 (no error)
410 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
411 * - the configuration read back from HAl has the same class Id
413 TEST_P(BroadcastRadioHidlTest, SetAndGetConfiguration) {
415 ASSERT_EQ(true, openTuner());
416 // test setConfiguration
417 mCallbackCalled = false;
418 Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[1]);
419 EXPECT_TRUE(hidlResult.isOk());
420 EXPECT_EQ(Result::OK, hidlResult);
421 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
422 EXPECT_EQ(Result::OK, mResultCallbackData);
423 EXPECT_EQ(mHalProperties.bands[1], mBandConfigCallbackData);
425 // test getConfiguration
426 BandConfig halConfig;
428 Return<void> hidlReturn =
429 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
431 if (result == Result::OK) {
435 EXPECT_TRUE(hidlReturn.isOk());
436 EXPECT_EQ(Result::OK, halResult);
437 EXPECT_EQ(mHalProperties.bands[1], halConfig);
441 * Test ITuner::setConfiguration() with invalid arguments.
444 * - the methods returns INVALID_ARGUMENTS on invalid arguments
445 * - the method recovers and succeeds after passing correct arguments
447 TEST_P(BroadcastRadioHidlTest, SetConfigurationFails) {
449 ASSERT_EQ(true, openTuner());
451 // Let's define a config that's bad for sure.
452 BandConfig badConfig = {};
453 badConfig.type = Band::FM;
454 badConfig.lowerLimit = 0xFFFFFFFF;
455 badConfig.upperLimit = 0;
456 badConfig.spacings = (std::vector<uint32_t>){ 0 };
458 // Test setConfiguration failing on bad data.
459 mCallbackCalled = false;
460 auto setResult = mTuner->setConfiguration(badConfig);
461 EXPECT_TRUE(setResult.isOk());
462 EXPECT_EQ(Result::INVALID_ARGUMENTS, setResult);
464 // Test setConfiguration recovering after passing good data.
465 mCallbackCalled = false;
466 setResult = mTuner->setConfiguration(mHalProperties.bands[0]);
467 EXPECT_TRUE(setResult.isOk());
468 EXPECT_EQ(Result::OK, setResult);
469 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
470 EXPECT_EQ(Result::OK, mResultCallbackData);
477 * - the HAL implements the method
478 * - the method returns 0 (no error)
479 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
480 * - skipping sub-channel or not does not fail the call
482 TEST_P(BroadcastRadioHidlTest, Scan) {
484 ASSERT_EQ(true, openTuner());
485 ASSERT_TRUE(checkAntenna());
487 mCallbackCalled = false;
488 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
489 EXPECT_TRUE(hidlResult.isOk());
490 EXPECT_EQ(Result::OK, hidlResult);
491 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
494 mCallbackCalled = false;
495 hidlResult = mTuner->scan(Direction::DOWN, false);
496 EXPECT_TRUE(hidlResult.isOk());
497 EXPECT_EQ(Result::OK, hidlResult);
498 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
505 * - the HAL implements the method
506 * - the method returns 0 (no error)
507 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
508 * - skipping sub-channel or not does not fail the call
510 TEST_P(BroadcastRadioHidlTest, Step) {
512 ASSERT_EQ(true, openTuner());
513 ASSERT_TRUE(checkAntenna());
515 mCallbackCalled = false;
516 Return<Result> hidlResult = mTuner->step(Direction::UP, false);
517 EXPECT_TRUE(hidlResult.isOk());
518 EXPECT_EQ(Result::OK, hidlResult);
519 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
522 mCallbackCalled = false;
523 hidlResult = mTuner->step(Direction::DOWN, true);
524 EXPECT_TRUE(hidlResult.isOk());
525 EXPECT_EQ(Result::OK, hidlResult);
526 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
530 * Test ITuner::tune, getProgramInformation and cancel methods
533 * - the HAL implements the methods
534 * - the methods return 0 (no error)
535 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
537 TEST_P(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
539 ASSERT_EQ(true, openTuner());
540 ASSERT_TRUE(checkAntenna());
543 ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
544 ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
547 uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
548 uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
549 uint32_t spacing = mHalProperties.bands[0].spacings[0];
552 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
553 mCallbackCalled = false;
554 mResultCallbackData = Result::NOT_INITIALIZED;
555 Return<Result> hidlResult = mTuner->tune(channel, 0);
556 EXPECT_TRUE(hidlResult.isOk());
557 EXPECT_EQ(Result::OK, hidlResult);
558 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
559 EXPECT_EQ(channel, mProgramInfoCallbackData.channel);
561 // test getProgramInformation
563 Result halResult = Result::NOT_INITIALIZED;
564 Return<void> hidlReturn = mTuner->getProgramInformation(
565 [&](Result result, const ProgramInfo& info) {
567 if (result == Result::OK) {
571 EXPECT_TRUE(hidlReturn.isOk());
572 EXPECT_EQ(Result::OK, halResult);
573 if (mResultCallbackData == Result::OK) {
574 EXPECT_EQ(true, halInfo.tuned);
575 EXPECT_LE(halInfo.channel, upperLimit);
576 EXPECT_GE(halInfo.channel, lowerLimit);
578 EXPECT_EQ(false, halInfo.tuned);
582 mTuner->tune(lowerLimit, 0);
583 hidlResult = mTuner->cancel();
584 EXPECT_TRUE(hidlResult.isOk());
585 EXPECT_EQ(Result::OK, hidlResult);
589 * Test ITuner::tune failing when channel out of the range is provided.
592 * - the method returns INVALID_ARGUMENTS when applicable
593 * - the method recovers and succeeds after passing correct arguments
595 TEST_P(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
597 ASSERT_TRUE(openTuner());
598 ASSERT_TRUE(checkAntenna());
600 // get current channel bounds
601 BandConfig halConfig;
603 auto configResult = mTuner->getConfiguration([&](Result result, const BandConfig& config) {
607 ASSERT_TRUE(configResult.isOk());
608 ASSERT_EQ(Result::OK, halResult);
610 // try to tune slightly above the limit and expect to fail
611 auto badChannel = halConfig.upperLimit + halConfig.spacings[0];
612 auto tuneResult = mTuner->tune(badChannel, 0);
613 EXPECT_TRUE(tuneResult.isOk());
614 EXPECT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
615 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
617 // tuning exactly at the limit should succeed
618 auto goodChannel = halConfig.upperLimit;
619 tuneResult = mTuner->tune(goodChannel, 0);
620 EXPECT_TRUE(tuneResult.isOk());
621 EXPECT_EQ(Result::OK, tuneResult);
622 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
625 INSTANTIATE_TEST_CASE_P(
626 BroadcastRadioHidlTestCases,
627 BroadcastRadioHidlTest,
628 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
630 int main(int argc, char** argv) {
631 ::testing::InitGoogleTest(&argc, argv);
632 int status = RUN_ALL_TESTS();
633 ALOGI("Test result = %d", status);