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