blob: 42127295a6addbb380e7a2c16416647f63671639 [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/**
308 * Test ITuner::setConfiguration() and getConfiguration methods
309 *
310 * Verifies that:
311 * - the HAL implements both methods
312 * - the methods return 0 (no error)
313 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
314 * - the configuration read back from HAl has the same class Id
315 */
316TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
317 ASSERT_EQ(true, openTuner());
318 // test setConfiguration
319 mCallbackCalled = false;
320 Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
Steven Morelandb6438422017-01-03 17:06:57 -0800321 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800322 EXPECT_EQ(Result::OK, hidlResult);
323 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
324 EXPECT_EQ(Result::OK, mResultCallbackData);
325
326 // test getConfiguration
327 BandConfig halConfig;
328 Result halResult;
329 Return<void> hidlReturn =
330 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
331 halResult = result;
332 if (result == Result::OK) {
333 halConfig = config;
334 }
335 });
Steven Morelandb6438422017-01-03 17:06:57 -0800336 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800337 EXPECT_EQ(Result::OK, halResult);
338 EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
339}
340
341/**
342 * Test ITuner::scan
343 *
344 * Verifies that:
345 * - the HAL implements the method
346 * - the method returns 0 (no error)
347 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
348 */
349TEST_F(BroadcastRadioHidlTest, Scan) {
350 ASSERT_EQ(true, openTuner());
351 ASSERT_TRUE(checkAntenna());
352 // test scan UP
353 mCallbackCalled = false;
354 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
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(kTuneCallbacktimeoutNs));
358
359 // test scan DOWN
360 mCallbackCalled = false;
361 hidlResult = mTuner->scan(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800362 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800363 EXPECT_EQ(Result::OK, hidlResult);
364 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
365}
366
367/**
368 * Test ITuner::step
369 *
370 * Verifies that:
371 * - the HAL implements the method
372 * - the method returns 0 (no error)
373 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
374 */
375TEST_F(BroadcastRadioHidlTest, Step) {
376 ASSERT_EQ(true, openTuner());
377 ASSERT_TRUE(checkAntenna());
378 // test step UP
379 mCallbackCalled = false;
380 Return<Result> hidlResult = mTuner->step(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800381 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800382 EXPECT_EQ(Result::OK, hidlResult);
383 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
384
385 // test step DOWN
386 mCallbackCalled = false;
387 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800388 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800389 EXPECT_EQ(Result::OK, hidlResult);
390 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
391}
392
393/**
394 * Test ITuner::tune, getProgramInformation and cancel methods
395 *
396 * Verifies that:
397 * - the HAL implements the methods
398 * - the methods return 0 (no error)
399 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
400 */
401TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
402 ASSERT_EQ(true, openTuner());
403 ASSERT_TRUE(checkAntenna());
404
405 // test tune
406 ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
407 ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
408
409 // test scan UP
410 uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
411 uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
412 uint32_t spacing = mHalProperties.bands[0].spacings[0];
413
414 uint32_t channel =
415 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
416 mCallbackCalled = false;
417 mResultCallbackData = Result::NOT_INITIALIZED;
418 Return<Result> hidlResult = mTuner->tune(channel, 0);
Steven Morelandb6438422017-01-03 17:06:57 -0800419 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800420 EXPECT_EQ(Result::OK, hidlResult);
421 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
422
423 // test getProgramInformation
424 ProgramInfo halInfo;
425 Result halResult = Result::NOT_INITIALIZED;
426 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800427 [&](Result result, const ProgramInfo& info) {
428 halResult = result;
429 if (result == Result::OK) {
430 halInfo = info;
431 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800432 });
Steven Morelandb6438422017-01-03 17:06:57 -0800433 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800434 EXPECT_EQ(Result::OK, halResult);
435 if (mResultCallbackData == Result::OK) {
436 EXPECT_EQ(true, halInfo.tuned);
437 EXPECT_LE(halInfo.channel, upperLimit);
438 EXPECT_GE(halInfo.channel, lowerLimit);
439 } else {
440 EXPECT_EQ(false, halInfo.tuned);
441 }
442
443 // test cancel
444 mTuner->tune(lowerLimit, 0);
445 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800446 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800447 EXPECT_EQ(Result::OK, hidlResult);
448}
449
450
451int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800452 ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
453 ::testing::InitGoogleTest(&argc, argv);
454 int status = RUN_ALL_TESTS();
455 ALOGI("Test result = %d", status);
456 return status;
457}