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