blob: 3ac659430432f6058802506bf3eb0a7ba039bd7c [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 Maed2bb4e2017-03-10 00:44:45 -080018#include <VtsHalHidlTargetTestBase.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;
Eric Laurent566fcda2016-11-23 10:36:36 -080036using ::android::hardware::Void;
37using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
38using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
39using ::android::hardware::broadcastradio::V1_0::ITuner;
40using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
41using ::android::hardware::broadcastradio::V1_0::Result;
42using ::android::hardware::broadcastradio::V1_0::Class;
43using ::android::hardware::broadcastradio::V1_0::Properties;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -080044using ::android::hardware::broadcastradio::V1_0::Band;
Eric Laurent566fcda2016-11-23 10:36:36 -080045using ::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 Wasilczyk2f461012017-03-14 11:19:15 -070051#define RETURN_IF_SKIPPED \
52 if (skipped) { \
53 std::cout << "[ SKIPPED ] This device class is not supported. " << std::endl; \
54 return; \
55 }
56
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080057// The main test class for Broadcast Radio HIDL HAL.
Eric Laurent566fcda2016-11-23 10:36:36 -080058
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070059class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
60 public ::testing::WithParamInterface<Class> {
Eric Laurent566fcda2016-11-23 10:36:36 -080061 protected:
62 virtual void SetUp() override {
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070063 ASSERT_EQ(nullptr, mRadio.get());
64
65 radioClass = GetParam();
66 skipped = false;
67
Eric Laurent566fcda2016-11-23 10:36:36 -080068 sp<IBroadcastRadioFactory> factory =
Yuexi Maed2bb4e2017-03-10 00:44:45 -080069 ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070070 ASSERT_NE(nullptr, factory.get());
71
72 Result connectResult;
73 factory->connectModule(radioClass, [&](Result ret, const sp<IBroadcastRadio>& radio) {
74 connectResult = ret;
75 mRadio = radio;
76 onCallback_l();
77 });
78 EXPECT_EQ(true, waitForCallback(kConnectCallbacktimeoutNs));
79 mCallbackCalled = false;
80
81 if (connectResult == Result::INVALID_ARGUMENTS) {
82 skipped = true;
83 return;
Eric Laurent566fcda2016-11-23 10:36:36 -080084 }
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070085 ASSERT_EQ(connectResult, Result::OK);
86
Eric Laurent566fcda2016-11-23 10:36:36 -080087 mTunerCallback = new MyCallback(this);
88 ASSERT_NE(nullptr, mRadio.get());
Eric Laurent566fcda2016-11-23 10:36:36 -080089 ASSERT_NE(nullptr, mTunerCallback.get());
90 }
91
92 virtual void TearDown() override {
93 mTuner.clear();
94 mRadio.clear();
95 }
96
97 class MyCallback : public ITunerCallback {
98 public:
99
100 // ITunerCallback methods (see doc in ITunerCallback.hal)
101 virtual Return<void> hardwareFailure() {
102 ALOGI("%s", __FUNCTION__);
103 mParentTest->onHwFailureCallback();
104 return Void();
105 }
106
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800107 virtual Return<void> configChange(Result result, const BandConfig& config) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800108 ALOGI("%s result %d", __FUNCTION__, result);
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800109 mParentTest->onConfigChangeCallback(result, config);
Eric Laurent566fcda2016-11-23 10:36:36 -0800110 return Void();
111 }
112
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800113 virtual Return<void> tuneComplete(Result result, const ProgramInfo& info) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800114 ALOGI("%s result %d", __FUNCTION__, result);
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800115 mParentTest->onTuneCompleteCallback(result, info);
Eric Laurent566fcda2016-11-23 10:36:36 -0800116 return Void();
117 }
118
119 virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
120 return Void();
121 }
122
123 virtual Return<void> antennaStateChange(bool connected) {
124 ALOGI("%s connected %d", __FUNCTION__, connected);
125 return Void();
126 }
127
128 virtual Return<void> trafficAnnouncement(bool active) {
129 ALOGI("%s active %d", __FUNCTION__, active);
130 return Void();
131 }
132
133 virtual Return<void> emergencyAnnouncement(bool active) {
134 ALOGI("%s active %d", __FUNCTION__, active);
135 return Void();
136 }
137
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__);
141 return Void();
142 }
143
144 MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
145
146 private:
147 // BroadcastRadioHidlTest instance to which callbacks will be notified.
148 BroadcastRadioHidlTest *mParentTest;
149 };
150
151
152 /**
153 * Method called by MyCallback when a callback with no status or boolean value is received
154 */
155 void onCallback() {
156 Mutex::Autolock _l(mLock);
157 onCallback_l();
158 }
159
160 /**
161 * Method called by MyCallback when hardwareFailure() callback is received
162 */
163 void onHwFailureCallback() {
164 Mutex::Autolock _l(mLock);
165 mHwFailure = true;
166 onCallback_l();
167 }
168
169 /**
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800170 * Method called by MyCallback when configChange() callback is received.
Eric Laurent566fcda2016-11-23 10:36:36 -0800171 */
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800172 void onConfigChangeCallback(Result result, const BandConfig& config) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800173 Mutex::Autolock _l(mLock);
174 mResultCallbackData = result;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800175 mBandConfigCallbackData = config;
176 onCallback_l();
177 }
178
179 /**
180 * Method called by MyCallback when tuneComplete() callback is received.
181 */
182 void onTuneCompleteCallback(Result result, const ProgramInfo& info) {
183 Mutex::Autolock _l(mLock);
184 mResultCallbackData = result;
185 mProgramInfoCallbackData = info;
Eric Laurent566fcda2016-11-23 10:36:36 -0800186 onCallback_l();
187 }
188
189 /**
190 * Method called by MyCallback when a boolean indication is received
191 */
192 void onBoolCallback(bool result) {
193 Mutex::Autolock _l(mLock);
194 mBoolCallbackData = result;
195 onCallback_l();
196 }
197
198
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700199 BroadcastRadioHidlTest()
200 : mCallbackCalled(false), mBoolCallbackData(false), mResultCallbackData(Result::OK),
201 mHwFailure(false) {}
Eric Laurent566fcda2016-11-23 10:36:36 -0800202
203 void onCallback_l() {
204 if (!mCallbackCalled) {
205 mCallbackCalled = true;
206 mCallbackCond.broadcast();
207 }
208 }
209
210
211 bool waitForCallback(nsecs_t reltime = 0) {
212 Mutex::Autolock _l(mLock);
213 nsecs_t endTime = systemTime() + reltime;
214 while (!mCallbackCalled) {
215 if (reltime == 0) {
216 mCallbackCond.wait(mLock);
217 } else {
218 nsecs_t now = systemTime();
219 if (now > endTime) {
220 return false;
221 }
222 mCallbackCond.waitRelative(mLock, endTime - now);
223 }
224 }
225 return true;
226 }
227
228 bool getProperties();
229 bool openTuner();
230 bool checkAntenna();
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700231 BandConfig& getBand(unsigned idx);
Eric Laurent566fcda2016-11-23 10:36:36 -0800232
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700233 static const nsecs_t kConnectCallbacktimeoutNs = seconds_to_nanoseconds(1);
Eric Laurent566fcda2016-11-23 10:36:36 -0800234 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
235 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
236
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700237 Class radioClass;
238 bool skipped;
Eric Laurent566fcda2016-11-23 10:36:36 -0800239 sp<IBroadcastRadio> mRadio;
240 Properties mHalProperties;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700241 bool mHalPropertiesInitialized = false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800242 sp<ITuner> mTuner;
243 sp<MyCallback> mTunerCallback;
244 Mutex mLock;
245 Condition mCallbackCond;
246 bool mCallbackCalled;
247 bool mBoolCallbackData;
248 Result mResultCallbackData;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800249 ProgramInfo mProgramInfoCallbackData;
250 BandConfig mBandConfigCallbackData;
Eric Laurent566fcda2016-11-23 10:36:36 -0800251 bool mHwFailure;
252};
253
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800254namespace android {
255namespace hardware {
256namespace broadcastradio {
257namespace V1_0 {
258
259/**
260 * Compares two BandConfig objects for testing purposes.
261 */
262static bool operator==(const BandConfig& l, const BandConfig& r) {
263 if (l.type != r.type) return false;
264 if (l.antennaConnected != r.antennaConnected) return false;
265 if (l.lowerLimit != r.lowerLimit) return false;
266 if (l.upperLimit != r.upperLimit) return false;
267 if (l.spacings != r.spacings) return false;
268 if (l.type == Band::AM || l.type == Band::AM_HD) {
269 return l.ext.am == r.ext.am;
270 } else if (l.type == Band::FM || l.type == Band::FM_HD) {
271 return l.ext.fm == r.ext.fm;
272 } else {
273 // unsupported type
274 return false;
275 }
276}
277
278} // V1_0
279} // broadcastradio
280} // hardware
281} // android
282
Eric Laurent566fcda2016-11-23 10:36:36 -0800283bool BroadcastRadioHidlTest::getProperties()
284{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700285 if (mHalPropertiesInitialized) return true;
Eric Laurent566fcda2016-11-23 10:36:36 -0800286
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700287 Result halResult = Result::NOT_INITIALIZED;
288 auto hidlReturn = mRadio->getProperties([&](Result result, const Properties& properties) {
289 halResult = result;
290 if (result == Result::OK) {
291 mHalProperties = properties;
292 }
293 });
294
295 EXPECT_TRUE(hidlReturn.isOk());
296 EXPECT_EQ(Result::OK, halResult);
297 EXPECT_EQ(radioClass, mHalProperties.classId);
298 EXPECT_GT(mHalProperties.numTuners, 0u);
299 if (radioClass == Class::AM_FM) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800300 EXPECT_GT(mHalProperties.bands.size(), 0u);
301 }
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700302
303 if (hidlReturn.isOk() && halResult == Result::OK) {
304 mHalPropertiesInitialized = true;
305 return true;
306 }
307 return false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800308}
309
310bool BroadcastRadioHidlTest::openTuner()
311{
312 if (!getProperties()) {
313 return false;
314 }
315 if (mTuner.get() == nullptr) {
316 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700317 auto openCb = [&](Result result, const sp<ITuner>& tuner) {
318 halResult = result;
319 if (result == Result::OK) {
320 mTuner = tuner;
321 }
322 };
323 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
Steven Morelandb6438422017-01-03 17:06:57 -0800324 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800325 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700326 if (radioClass == Class::AM_FM) {
327 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
328 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800329 }
330 EXPECT_NE(nullptr, mTuner.get());
331 return nullptr != mTuner.get();
332}
333
334bool BroadcastRadioHidlTest::checkAntenna()
335{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700336 if (radioClass != Class::AM_FM) return true;
337
Eric Laurent566fcda2016-11-23 10:36:36 -0800338 BandConfig halConfig;
339 Result halResult = Result::NOT_INITIALIZED;
340 Return<void> hidlReturn =
341 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
342 halResult = result;
343 if (result == Result::OK) {
344 halConfig = config;
345 }
346 });
347
348 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
349}
350
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700351BandConfig& BroadcastRadioHidlTest::getBand(unsigned idx) {
352 static BandConfig dummyBandConfig = {};
353 if (radioClass == Class::AM_FM) {
354 EXPECT_GT(mHalProperties.bands.size(), idx);
355 if (mHalProperties.bands.size() > idx) {
356 return mHalProperties.bands[idx];
357 } else {
358 return dummyBandConfig;
359 }
360 } else {
361 return dummyBandConfig;
362 }
363}
Eric Laurent566fcda2016-11-23 10:36:36 -0800364
365/**
366 * Test IBroadcastRadio::getProperties() method
367 *
368 * Verifies that:
369 * - the HAL implements the method
370 * - the method returns 0 (no error)
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700371 * - the implementation class is radioClass
Eric Laurent566fcda2016-11-23 10:36:36 -0800372 * - the implementation supports at least one tuner
373 * - the implementation supports at one band
374 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700375TEST_P(BroadcastRadioHidlTest, GetProperties) {
376 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800377 EXPECT_EQ(true, getProperties());
378}
379
380/**
381 * Test IBroadcastRadio::openTuner() method
382 *
383 * Verifies that:
384 * - the HAL implements the method
385 * - the method returns 0 (no error) and a valid ITuner interface
386 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700387TEST_P(BroadcastRadioHidlTest, OpenTuner) {
388 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800389 EXPECT_EQ(true, openTuner());
390}
391
392/**
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800393 * Test IBroadcastRadio::openTuner() after ITuner disposal.
394 *
395 * Verifies that:
396 * - ITuner destruction gets propagated through HAL
397 * - the openTuner method works well when called for the second time
398 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700399TEST_P(BroadcastRadioHidlTest, ReopenTuner) {
400 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800401 EXPECT_TRUE(openTuner());
402 mTuner.clear();
403 EXPECT_TRUE(openTuner());
404}
405
406/**
407 * Test IBroadcastRadio::openTuner() method called twice.
408 *
409 * Verifies that:
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700410 * - the openTuner method fails with INVALID_STATE or succeeds when called for the second time
411 * without deleting previous ITuner instance
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800412 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700413TEST_P(BroadcastRadioHidlTest, OpenTunerTwice) {
414 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800415 EXPECT_TRUE(openTuner());
416
417 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700418 auto openCb = [&](Result result, const sp<ITuner>&) { halResult = result; };
419 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800420 EXPECT_TRUE(hidlReturn.isOk());
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700421 if (halResult == Result::INVALID_STATE) {
422 EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
423 }
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800424}
425
426/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800427 * Test ITuner::setConfiguration() and getConfiguration methods
428 *
429 * Verifies that:
430 * - the HAL implements both methods
431 * - the methods return 0 (no error)
432 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
433 * - the configuration read back from HAl has the same class Id
434 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700435TEST_P(BroadcastRadioHidlTest, SetAndGetConfiguration) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700436 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700437 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800438 ASSERT_EQ(true, openTuner());
439 // test setConfiguration
440 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700441 Return<Result> hidlResult = mTuner->setConfiguration(getBand(1));
Steven Morelandb6438422017-01-03 17:06:57 -0800442 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800443 EXPECT_EQ(Result::OK, hidlResult);
444 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
445 EXPECT_EQ(Result::OK, mResultCallbackData);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700446 EXPECT_EQ(getBand(1), mBandConfigCallbackData);
Eric Laurent566fcda2016-11-23 10:36:36 -0800447
448 // test getConfiguration
449 BandConfig halConfig;
450 Result halResult;
451 Return<void> hidlReturn =
452 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
453 halResult = result;
454 if (result == Result::OK) {
455 halConfig = config;
456 }
457 });
Steven Morelandb6438422017-01-03 17:06:57 -0800458 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800459 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700460 EXPECT_EQ(getBand(1), halConfig);
Eric Laurent566fcda2016-11-23 10:36:36 -0800461}
462
463/**
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800464 * Test ITuner::setConfiguration() with invalid arguments.
465 *
466 * Verifies that:
467 * - the methods returns INVALID_ARGUMENTS on invalid arguments
468 * - the method recovers and succeeds after passing correct arguments
469 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700470TEST_P(BroadcastRadioHidlTest, SetConfigurationFails) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700471 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700472 RETURN_IF_SKIPPED;
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800473 ASSERT_EQ(true, openTuner());
474
475 // Let's define a config that's bad for sure.
476 BandConfig badConfig = {};
477 badConfig.type = Band::FM;
478 badConfig.lowerLimit = 0xFFFFFFFF;
479 badConfig.upperLimit = 0;
480 badConfig.spacings = (std::vector<uint32_t>){ 0 };
481
482 // Test setConfiguration failing on bad data.
483 mCallbackCalled = false;
484 auto setResult = mTuner->setConfiguration(badConfig);
485 EXPECT_TRUE(setResult.isOk());
486 EXPECT_EQ(Result::INVALID_ARGUMENTS, setResult);
487
488 // Test setConfiguration recovering after passing good data.
489 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700490 setResult = mTuner->setConfiguration(getBand(0));
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800491 EXPECT_TRUE(setResult.isOk());
492 EXPECT_EQ(Result::OK, setResult);
493 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
494 EXPECT_EQ(Result::OK, mResultCallbackData);
495}
496
497/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800498 * Test ITuner::scan
499 *
500 * Verifies that:
501 * - the HAL implements the method
502 * - the method returns 0 (no error)
503 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700504 * - skipping sub-channel or not does not fail the call
Eric Laurent566fcda2016-11-23 10:36:36 -0800505 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700506TEST_P(BroadcastRadioHidlTest, Scan) {
507 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800508 ASSERT_EQ(true, openTuner());
509 ASSERT_TRUE(checkAntenna());
510 // test scan UP
511 mCallbackCalled = false;
512 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800513 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800514 EXPECT_EQ(Result::OK, hidlResult);
515 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
516
517 // test scan DOWN
518 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700519 hidlResult = mTuner->scan(Direction::DOWN, false);
Steven Morelandb6438422017-01-03 17:06:57 -0800520 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800521 EXPECT_EQ(Result::OK, hidlResult);
522 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
523}
524
525/**
526 * Test ITuner::step
527 *
528 * Verifies that:
529 * - the HAL implements the method
530 * - the method returns 0 (no error)
531 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700532 * - skipping sub-channel or not does not fail the call
Eric Laurent566fcda2016-11-23 10:36:36 -0800533 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700534TEST_P(BroadcastRadioHidlTest, Step) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700535 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700536 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800537 ASSERT_EQ(true, openTuner());
538 ASSERT_TRUE(checkAntenna());
539 // test step UP
540 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700541 Return<Result> hidlResult = mTuner->step(Direction::UP, false);
Steven Morelandb6438422017-01-03 17:06:57 -0800542 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800543 EXPECT_EQ(Result::OK, hidlResult);
544 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
545
546 // test step DOWN
547 mCallbackCalled = false;
548 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800549 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800550 EXPECT_EQ(Result::OK, hidlResult);
551 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
552}
553
554/**
555 * Test ITuner::tune, getProgramInformation and cancel methods
556 *
557 * Verifies that:
558 * - the HAL implements the methods
559 * - the methods return 0 (no error)
560 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
561 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700562TEST_P(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700563 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700564 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800565 ASSERT_EQ(true, openTuner());
566 ASSERT_TRUE(checkAntenna());
567
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700568 auto& band = getBand(0);
569
Eric Laurent566fcda2016-11-23 10:36:36 -0800570 // test tune
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700571 ASSERT_GT(band.spacings.size(), 0u);
572 ASSERT_GT(band.upperLimit, band.lowerLimit);
Eric Laurent566fcda2016-11-23 10:36:36 -0800573
574 // test scan UP
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700575 uint32_t lowerLimit = band.lowerLimit;
576 uint32_t upperLimit = band.upperLimit;
577 uint32_t spacing = band.spacings[0];
Eric Laurent566fcda2016-11-23 10:36:36 -0800578
579 uint32_t channel =
580 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
581 mCallbackCalled = false;
582 mResultCallbackData = Result::NOT_INITIALIZED;
583 Return<Result> hidlResult = mTuner->tune(channel, 0);
Steven Morelandb6438422017-01-03 17:06:57 -0800584 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800585 EXPECT_EQ(Result::OK, hidlResult);
586 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800587 EXPECT_EQ(channel, mProgramInfoCallbackData.channel);
Eric Laurent566fcda2016-11-23 10:36:36 -0800588
589 // test getProgramInformation
590 ProgramInfo halInfo;
591 Result halResult = Result::NOT_INITIALIZED;
592 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800593 [&](Result result, const ProgramInfo& info) {
594 halResult = result;
595 if (result == Result::OK) {
596 halInfo = info;
597 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800598 });
Steven Morelandb6438422017-01-03 17:06:57 -0800599 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800600 EXPECT_EQ(Result::OK, halResult);
601 if (mResultCallbackData == Result::OK) {
602 EXPECT_EQ(true, halInfo.tuned);
603 EXPECT_LE(halInfo.channel, upperLimit);
604 EXPECT_GE(halInfo.channel, lowerLimit);
605 } else {
606 EXPECT_EQ(false, halInfo.tuned);
607 }
608
609 // test cancel
610 mTuner->tune(lowerLimit, 0);
611 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800612 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800613 EXPECT_EQ(Result::OK, hidlResult);
614}
615
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800616/**
617 * Test ITuner::tune failing when channel out of the range is provided.
618 *
619 * Verifies that:
620 * - the method returns INVALID_ARGUMENTS when applicable
621 * - the method recovers and succeeds after passing correct arguments
622 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700623TEST_P(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700624 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700625 RETURN_IF_SKIPPED;
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800626 ASSERT_TRUE(openTuner());
627 ASSERT_TRUE(checkAntenna());
628
629 // get current channel bounds
630 BandConfig halConfig;
631 Result halResult;
632 auto configResult = mTuner->getConfiguration([&](Result result, const BandConfig& config) {
633 halResult = result;
634 halConfig = config;
635 });
636 ASSERT_TRUE(configResult.isOk());
637 ASSERT_EQ(Result::OK, halResult);
638
639 // try to tune slightly above the limit and expect to fail
640 auto badChannel = halConfig.upperLimit + halConfig.spacings[0];
641 auto tuneResult = mTuner->tune(badChannel, 0);
642 EXPECT_TRUE(tuneResult.isOk());
643 EXPECT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
644 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
645
646 // tuning exactly at the limit should succeed
647 auto goodChannel = halConfig.upperLimit;
648 tuneResult = mTuner->tune(goodChannel, 0);
649 EXPECT_TRUE(tuneResult.isOk());
650 EXPECT_EQ(Result::OK, tuneResult);
651 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
652}
653
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700654INSTANTIATE_TEST_CASE_P(
655 BroadcastRadioHidlTestCases,
656 BroadcastRadioHidlTest,
657 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
Eric Laurent566fcda2016-11-23 10:36:36 -0800658
659int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800660 ::testing::InitGoogleTest(&argc, argv);
661 int status = RUN_ALL_TESTS();
662 ALOGI("Test result = %d", status);
663 return status;
664}