blob: 4268ddd3e83d48dd2b35e0fb866207331993baa1 [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"
Yuexi Ma50d7e272017-02-28 01:46:51 -080018#include <VtsHalHidlTargetBaseTest.h>
Eric Laurent566fcda2016-11-23 10:36:36 -080019#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
Yuexi Ma50d7e272017-02-28 01:46:51 -080053class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetBaseTest {
Eric Laurent566fcda2016-11-23 10:36:36 -080054 protected:
55 virtual void SetUp() override {
Eric Laurent566fcda2016-11-23 10:36:36 -080056 sp<IBroadcastRadioFactory> factory =
Yuexi Ma50d7e272017-02-28 01:46:51 -080057 ::testing::VtsHalHidlTargetBaseTest::getService<IBroadcastRadioFactory>();
Eric Laurent566fcda2016-11-23 10:36:36 -080058 if (factory != 0) {
59 factory->connectModule(Class::AM_FM,
60 [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
61 if (retval == Result::OK) {
62 mRadio = result;
63 }
64 });
65 }
66 mTunerCallback = new MyCallback(this);
67 ASSERT_NE(nullptr, mRadio.get());
Eric Laurent566fcda2016-11-23 10:36:36 -080068 ASSERT_NE(nullptr, mTunerCallback.get());
69 }
70
71 virtual void TearDown() override {
72 mTuner.clear();
73 mRadio.clear();
74 }
75
76 class MyCallback : public ITunerCallback {
77 public:
78
79 // ITunerCallback methods (see doc in ITunerCallback.hal)
80 virtual Return<void> hardwareFailure() {
81 ALOGI("%s", __FUNCTION__);
82 mParentTest->onHwFailureCallback();
83 return Void();
84 }
85
86 virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
87 ALOGI("%s result %d", __FUNCTION__, result);
88 mParentTest->onResultCallback(result);
89 return Void();
90 }
91
92 virtual Return<void> tuneComplete(Result result, const ProgramInfo& info __unused) {
93 ALOGI("%s result %d", __FUNCTION__, result);
94 mParentTest->onResultCallback(result);
95 return Void();
96 }
97
98 virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
99 return Void();
100 }
101
102 virtual Return<void> antennaStateChange(bool connected) {
103 ALOGI("%s connected %d", __FUNCTION__, connected);
104 return Void();
105 }
106
107 virtual Return<void> trafficAnnouncement(bool active) {
108 ALOGI("%s active %d", __FUNCTION__, active);
109 return Void();
110 }
111
112 virtual Return<void> emergencyAnnouncement(bool active) {
113 ALOGI("%s active %d", __FUNCTION__, active);
114 return Void();
115 }
116
117 virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
118 const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
119 ALOGI("%s", __FUNCTION__);
120 return Void();
121 }
122
123 MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
124
125 private:
126 // BroadcastRadioHidlTest instance to which callbacks will be notified.
127 BroadcastRadioHidlTest *mParentTest;
128 };
129
130
131 /**
132 * Method called by MyCallback when a callback with no status or boolean value is received
133 */
134 void onCallback() {
135 Mutex::Autolock _l(mLock);
136 onCallback_l();
137 }
138
139 /**
140 * Method called by MyCallback when hardwareFailure() callback is received
141 */
142 void onHwFailureCallback() {
143 Mutex::Autolock _l(mLock);
144 mHwFailure = true;
145 onCallback_l();
146 }
147
148 /**
149 * Method called by MyCallback when a callback with status is received
150 */
151 void onResultCallback(Result result) {
152 Mutex::Autolock _l(mLock);
153 mResultCallbackData = result;
154 onCallback_l();
155 }
156
157 /**
158 * Method called by MyCallback when a boolean indication is received
159 */
160 void onBoolCallback(bool result) {
161 Mutex::Autolock _l(mLock);
162 mBoolCallbackData = result;
163 onCallback_l();
164 }
165
166
167 BroadcastRadioHidlTest() :
168 mCallbackCalled(false), mBoolCallbackData(false),
169 mResultCallbackData(Result::OK), mHwFailure(false) {}
170
171 void onCallback_l() {
172 if (!mCallbackCalled) {
173 mCallbackCalled = true;
174 mCallbackCond.broadcast();
175 }
176 }
177
178
179 bool waitForCallback(nsecs_t reltime = 0) {
180 Mutex::Autolock _l(mLock);
181 nsecs_t endTime = systemTime() + reltime;
182 while (!mCallbackCalled) {
183 if (reltime == 0) {
184 mCallbackCond.wait(mLock);
185 } else {
186 nsecs_t now = systemTime();
187 if (now > endTime) {
188 return false;
189 }
190 mCallbackCond.waitRelative(mLock, endTime - now);
191 }
192 }
193 return true;
194 }
195
196 bool getProperties();
197 bool openTuner();
198 bool checkAntenna();
199
200 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
201 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
202
203 sp<IBroadcastRadio> mRadio;
204 Properties mHalProperties;
205 sp<ITuner> mTuner;
206 sp<MyCallback> mTunerCallback;
207 Mutex mLock;
208 Condition mCallbackCond;
209 bool mCallbackCalled;
210 bool mBoolCallbackData;
211 Result mResultCallbackData;
212 bool mHwFailure;
213};
214
215// A class for test environment setup (kept since this file is a template).
216class BroadcastRadioHidlEnvironment : public ::testing::Environment {
217 public:
218 virtual void SetUp() {}
219 virtual void TearDown() {}
220};
221
222bool BroadcastRadioHidlTest::getProperties()
223{
224 if (mHalProperties.bands.size() == 0) {
225 Result halResult = Result::NOT_INITIALIZED;
226 Return<void> hidlReturn =
227 mRadio->getProperties([&](Result result, const Properties& properties) {
228 halResult = result;
229 if (result == Result::OK) {
230 mHalProperties = properties;
231 }
232 });
233
Steven Morelandb6438422017-01-03 17:06:57 -0800234 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800235 EXPECT_EQ(Result::OK, halResult);
236 EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
237 EXPECT_GT(mHalProperties.numTuners, 0u);
238 EXPECT_GT(mHalProperties.bands.size(), 0u);
239 }
240 return mHalProperties.bands.size() > 0;
241}
242
243bool BroadcastRadioHidlTest::openTuner()
244{
245 if (!getProperties()) {
246 return false;
247 }
248 if (mTuner.get() == nullptr) {
249 Result halResult = Result::NOT_INITIALIZED;
250 Return<void> hidlReturn =
251 mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
252 [&](Result result, const sp<ITuner>& tuner) {
253 halResult = result;
254 if (result == Result::OK) {
255 mTuner = tuner;
256 }
257 });
Steven Morelandb6438422017-01-03 17:06:57 -0800258 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800259 EXPECT_EQ(Result::OK, halResult);
260 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
261 }
262 EXPECT_NE(nullptr, mTuner.get());
263 return nullptr != mTuner.get();
264}
265
266bool BroadcastRadioHidlTest::checkAntenna()
267{
268 BandConfig halConfig;
269 Result halResult = Result::NOT_INITIALIZED;
270 Return<void> hidlReturn =
271 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
272 halResult = result;
273 if (result == Result::OK) {
274 halConfig = config;
275 }
276 });
277
278 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
279}
280
281
282/**
283 * Test IBroadcastRadio::getProperties() method
284 *
285 * Verifies that:
286 * - the HAL implements the method
287 * - the method returns 0 (no error)
288 * - the implementation class is AM_FM
289 * - the implementation supports at least one tuner
290 * - the implementation supports at one band
291 */
292TEST_F(BroadcastRadioHidlTest, GetProperties) {
293 EXPECT_EQ(true, getProperties());
294}
295
296/**
297 * Test IBroadcastRadio::openTuner() method
298 *
299 * Verifies that:
300 * - the HAL implements the method
301 * - the method returns 0 (no error) and a valid ITuner interface
302 */
303TEST_F(BroadcastRadioHidlTest, OpenTuner) {
304 EXPECT_EQ(true, openTuner());
305}
306
307/**
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800308 * Test IBroadcastRadio::openTuner() after ITuner disposal.
309 *
310 * Verifies that:
311 * - ITuner destruction gets propagated through HAL
312 * - the openTuner method works well when called for the second time
313 */
314TEST_F(BroadcastRadioHidlTest, ReopenTuner) {
315 EXPECT_TRUE(openTuner());
316 mTuner.clear();
317 EXPECT_TRUE(openTuner());
318}
319
320/**
321 * Test IBroadcastRadio::openTuner() method called twice.
322 *
323 * Verifies that:
324 * - the openTuner method fails when called for the second time without deleting previous
325 * ITuner instance
326 */
327TEST_F(BroadcastRadioHidlTest, OpenTunerTwice) {
328 EXPECT_TRUE(openTuner());
329
330 Result halResult = Result::NOT_INITIALIZED;
331 Return<void> hidlReturn =
332 mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
333 [&](Result result, const sp<ITuner>&) {
334 halResult = result;
335 });
336 EXPECT_TRUE(hidlReturn.isOk());
337 EXPECT_EQ(Result::INVALID_STATE, halResult);
338 EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
339}
340
341/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800342 * Test ITuner::setConfiguration() and getConfiguration methods
343 *
344 * Verifies that:
345 * - the HAL implements both methods
346 * - the methods return 0 (no error)
347 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
348 * - the configuration read back from HAl has the same class Id
349 */
350TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
351 ASSERT_EQ(true, openTuner());
352 // test setConfiguration
353 mCallbackCalled = false;
354 Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
Steven Morelandb6438422017-01-03 17:06:57 -0800355 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800356 EXPECT_EQ(Result::OK, hidlResult);
357 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
358 EXPECT_EQ(Result::OK, mResultCallbackData);
359
360 // test getConfiguration
361 BandConfig halConfig;
362 Result halResult;
363 Return<void> hidlReturn =
364 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
365 halResult = result;
366 if (result == Result::OK) {
367 halConfig = config;
368 }
369 });
Steven Morelandb6438422017-01-03 17:06:57 -0800370 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800371 EXPECT_EQ(Result::OK, halResult);
372 EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
373}
374
375/**
376 * Test ITuner::scan
377 *
378 * Verifies that:
379 * - the HAL implements the method
380 * - the method returns 0 (no error)
381 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
382 */
383TEST_F(BroadcastRadioHidlTest, Scan) {
384 ASSERT_EQ(true, openTuner());
385 ASSERT_TRUE(checkAntenna());
386 // test scan UP
387 mCallbackCalled = false;
388 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800389 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800390 EXPECT_EQ(Result::OK, hidlResult);
391 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
392
393 // test scan DOWN
394 mCallbackCalled = false;
395 hidlResult = mTuner->scan(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800396 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800397 EXPECT_EQ(Result::OK, hidlResult);
398 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
399}
400
401/**
402 * Test ITuner::step
403 *
404 * Verifies that:
405 * - the HAL implements the method
406 * - the method returns 0 (no error)
407 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
408 */
409TEST_F(BroadcastRadioHidlTest, Step) {
410 ASSERT_EQ(true, openTuner());
411 ASSERT_TRUE(checkAntenna());
412 // test step UP
413 mCallbackCalled = false;
414 Return<Result> hidlResult = mTuner->step(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800415 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800416 EXPECT_EQ(Result::OK, hidlResult);
417 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
418
419 // test step DOWN
420 mCallbackCalled = false;
421 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800422 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800423 EXPECT_EQ(Result::OK, hidlResult);
424 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
425}
426
427/**
428 * Test ITuner::tune, getProgramInformation and cancel methods
429 *
430 * Verifies that:
431 * - the HAL implements the methods
432 * - the methods return 0 (no error)
433 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
434 */
435TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
436 ASSERT_EQ(true, openTuner());
437 ASSERT_TRUE(checkAntenna());
438
439 // test tune
440 ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
441 ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
442
443 // test scan UP
444 uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
445 uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
446 uint32_t spacing = mHalProperties.bands[0].spacings[0];
447
448 uint32_t channel =
449 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
450 mCallbackCalled = false;
451 mResultCallbackData = Result::NOT_INITIALIZED;
452 Return<Result> hidlResult = mTuner->tune(channel, 0);
Steven Morelandb6438422017-01-03 17:06:57 -0800453 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800454 EXPECT_EQ(Result::OK, hidlResult);
455 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
456
457 // test getProgramInformation
458 ProgramInfo halInfo;
459 Result halResult = Result::NOT_INITIALIZED;
460 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800461 [&](Result result, const ProgramInfo& info) {
462 halResult = result;
463 if (result == Result::OK) {
464 halInfo = info;
465 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800466 });
Steven Morelandb6438422017-01-03 17:06:57 -0800467 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800468 EXPECT_EQ(Result::OK, halResult);
469 if (mResultCallbackData == Result::OK) {
470 EXPECT_EQ(true, halInfo.tuned);
471 EXPECT_LE(halInfo.channel, upperLimit);
472 EXPECT_GE(halInfo.channel, lowerLimit);
473 } else {
474 EXPECT_EQ(false, halInfo.tuned);
475 }
476
477 // test cancel
478 mTuner->tune(lowerLimit, 0);
479 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800480 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800481 EXPECT_EQ(Result::OK, hidlResult);
482}
483
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800484/**
485 * Test ITuner::tune failing when channel out of the range is provided.
486 *
487 * Verifies that:
488 * - the method returns INVALID_ARGUMENTS when applicable
489 * - the method recovers and succeeds after passing correct arguments
490 */
491TEST_F(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
492 ASSERT_TRUE(openTuner());
493 ASSERT_TRUE(checkAntenna());
494
495 // get current channel bounds
496 BandConfig halConfig;
497 Result halResult;
498 auto configResult = mTuner->getConfiguration([&](Result result, const BandConfig& config) {
499 halResult = result;
500 halConfig = config;
501 });
502 ASSERT_TRUE(configResult.isOk());
503 ASSERT_EQ(Result::OK, halResult);
504
505 // try to tune slightly above the limit and expect to fail
506 auto badChannel = halConfig.upperLimit + halConfig.spacings[0];
507 auto tuneResult = mTuner->tune(badChannel, 0);
508 EXPECT_TRUE(tuneResult.isOk());
509 EXPECT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
510 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
511
512 // tuning exactly at the limit should succeed
513 auto goodChannel = halConfig.upperLimit;
514 tuneResult = mTuner->tune(goodChannel, 0);
515 EXPECT_TRUE(tuneResult.isOk());
516 EXPECT_EQ(Result::OK, tuneResult);
517 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
518}
519
Eric Laurent566fcda2016-11-23 10:36:36 -0800520
521int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800522 ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
523 ::testing::InitGoogleTest(&argc, argv);
524 int status = RUN_ALL_TESTS();
525 ALOGI("Test result = %d", status);
526 return status;
527}