blob: fa0f030d09c8e4edacfa7dadf304088c0f9beb5f [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;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -070049using ::android::hardware::broadcastradio::V1_0::MetadataKey;
50using ::android::hardware::broadcastradio::V1_0::MetadataType;
Eric Laurent566fcda2016-11-23 10:36:36 -080051
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070052#define RETURN_IF_SKIPPED \
53 if (skipped) { \
54 std::cout << "[ SKIPPED ] This device class is not supported. " << std::endl; \
55 return; \
56 }
57
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080058// The main test class for Broadcast Radio HIDL HAL.
Eric Laurent566fcda2016-11-23 10:36:36 -080059
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070060class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase,
61 public ::testing::WithParamInterface<Class> {
Eric Laurent566fcda2016-11-23 10:36:36 -080062 protected:
63 virtual void SetUp() override {
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070064 ASSERT_EQ(nullptr, mRadio.get());
65
66 radioClass = GetParam();
67 skipped = false;
68
Eric Laurent566fcda2016-11-23 10:36:36 -080069 sp<IBroadcastRadioFactory> factory =
Yuexi Maed2bb4e2017-03-10 00:44:45 -080070 ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070071 ASSERT_NE(nullptr, factory.get());
72
73 Result connectResult;
74 factory->connectModule(radioClass, [&](Result ret, const sp<IBroadcastRadio>& radio) {
75 connectResult = ret;
76 mRadio = radio;
77 onCallback_l();
78 });
79 EXPECT_EQ(true, waitForCallback(kConnectCallbacktimeoutNs));
80 mCallbackCalled = false;
81
82 if (connectResult == Result::INVALID_ARGUMENTS) {
83 skipped = true;
84 return;
Eric Laurent566fcda2016-11-23 10:36:36 -080085 }
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -070086 ASSERT_EQ(connectResult, Result::OK);
87
Eric Laurent566fcda2016-11-23 10:36:36 -080088 mTunerCallback = new MyCallback(this);
89 ASSERT_NE(nullptr, mRadio.get());
Eric Laurent566fcda2016-11-23 10:36:36 -080090 ASSERT_NE(nullptr, mTunerCallback.get());
91 }
92
93 virtual void TearDown() override {
94 mTuner.clear();
95 mRadio.clear();
96 }
97
98 class MyCallback : public ITunerCallback {
99 public:
100
101 // ITunerCallback methods (see doc in ITunerCallback.hal)
102 virtual Return<void> hardwareFailure() {
103 ALOGI("%s", __FUNCTION__);
104 mParentTest->onHwFailureCallback();
105 return Void();
106 }
107
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800108 virtual Return<void> configChange(Result result, const BandConfig& config) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800109 ALOGI("%s result %d", __FUNCTION__, result);
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800110 mParentTest->onConfigChangeCallback(result, config);
Eric Laurent566fcda2016-11-23 10:36:36 -0800111 return Void();
112 }
113
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800114 virtual Return<void> tuneComplete(Result result, const ProgramInfo& info) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800115 ALOGI("%s result %d", __FUNCTION__, result);
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800116 mParentTest->onTuneCompleteCallback(result, info);
Eric Laurent566fcda2016-11-23 10:36:36 -0800117 return Void();
118 }
119
120 virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
121 return Void();
122 }
123
124 virtual Return<void> antennaStateChange(bool connected) {
125 ALOGI("%s connected %d", __FUNCTION__, connected);
126 return Void();
127 }
128
129 virtual Return<void> trafficAnnouncement(bool active) {
130 ALOGI("%s active %d", __FUNCTION__, active);
131 return Void();
132 }
133
134 virtual Return<void> emergencyAnnouncement(bool active) {
135 ALOGI("%s active %d", __FUNCTION__, active);
136 return Void();
137 }
138
139 virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
140 const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
141 ALOGI("%s", __FUNCTION__);
142 return Void();
143 }
144
145 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 /**
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800171 * Method called by MyCallback when configChange() callback is received.
Eric Laurent566fcda2016-11-23 10:36:36 -0800172 */
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800173 void onConfigChangeCallback(Result result, const BandConfig& config) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800174 Mutex::Autolock _l(mLock);
175 mResultCallbackData = result;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800176 mBandConfigCallbackData = config;
177 onCallback_l();
178 }
179
180 /**
181 * Method called by MyCallback when tuneComplete() callback is received.
182 */
183 void onTuneCompleteCallback(Result result, const ProgramInfo& info) {
184 Mutex::Autolock _l(mLock);
185 mResultCallbackData = result;
186 mProgramInfoCallbackData = info;
Eric Laurent566fcda2016-11-23 10:36:36 -0800187 onCallback_l();
188 }
189
190 /**
191 * Method called by MyCallback when a boolean indication is received
192 */
193 void onBoolCallback(bool result) {
194 Mutex::Autolock _l(mLock);
195 mBoolCallbackData = result;
196 onCallback_l();
197 }
198
199
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700200 BroadcastRadioHidlTest()
201 : mCallbackCalled(false), mBoolCallbackData(false), mResultCallbackData(Result::OK),
202 mHwFailure(false) {}
Eric Laurent566fcda2016-11-23 10:36:36 -0800203
204 void onCallback_l() {
205 if (!mCallbackCalled) {
206 mCallbackCalled = true;
207 mCallbackCond.broadcast();
208 }
209 }
210
211
212 bool waitForCallback(nsecs_t reltime = 0) {
213 Mutex::Autolock _l(mLock);
214 nsecs_t endTime = systemTime() + reltime;
215 while (!mCallbackCalled) {
216 if (reltime == 0) {
217 mCallbackCond.wait(mLock);
218 } else {
219 nsecs_t now = systemTime();
220 if (now > endTime) {
221 return false;
222 }
223 mCallbackCond.waitRelative(mLock, endTime - now);
224 }
225 }
226 return true;
227 }
228
229 bool getProperties();
230 bool openTuner();
231 bool checkAntenna();
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700232 BandConfig& getBand(unsigned idx);
Eric Laurent566fcda2016-11-23 10:36:36 -0800233
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700234 static const nsecs_t kConnectCallbacktimeoutNs = seconds_to_nanoseconds(1);
Eric Laurent566fcda2016-11-23 10:36:36 -0800235 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
236 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
237
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700238 Class radioClass;
239 bool skipped;
Eric Laurent566fcda2016-11-23 10:36:36 -0800240 sp<IBroadcastRadio> mRadio;
241 Properties mHalProperties;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700242 bool mHalPropertiesInitialized = false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800243 sp<ITuner> mTuner;
244 sp<MyCallback> mTunerCallback;
245 Mutex mLock;
246 Condition mCallbackCond;
247 bool mCallbackCalled;
248 bool mBoolCallbackData;
249 Result mResultCallbackData;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800250 ProgramInfo mProgramInfoCallbackData;
251 BandConfig mBandConfigCallbackData;
Eric Laurent566fcda2016-11-23 10:36:36 -0800252 bool mHwFailure;
253};
254
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800255namespace android {
256namespace hardware {
257namespace broadcastradio {
258namespace V1_0 {
259
260/**
261 * Compares two BandConfig objects for testing purposes.
262 */
263static bool operator==(const BandConfig& l, const BandConfig& r) {
264 if (l.type != r.type) return false;
265 if (l.antennaConnected != r.antennaConnected) return false;
266 if (l.lowerLimit != r.lowerLimit) return false;
267 if (l.upperLimit != r.upperLimit) return false;
268 if (l.spacings != r.spacings) return false;
269 if (l.type == Band::AM || l.type == Band::AM_HD) {
270 return l.ext.am == r.ext.am;
271 } else if (l.type == Band::FM || l.type == Band::FM_HD) {
272 return l.ext.fm == r.ext.fm;
273 } else {
274 // unsupported type
275 return false;
276 }
277}
278
279} // V1_0
280} // broadcastradio
281} // hardware
282} // android
283
Eric Laurent566fcda2016-11-23 10:36:36 -0800284bool BroadcastRadioHidlTest::getProperties()
285{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700286 if (mHalPropertiesInitialized) return true;
Eric Laurent566fcda2016-11-23 10:36:36 -0800287
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700288 Result halResult = Result::NOT_INITIALIZED;
289 auto hidlReturn = mRadio->getProperties([&](Result result, const Properties& properties) {
290 halResult = result;
291 if (result == Result::OK) {
292 mHalProperties = properties;
293 }
294 });
295
296 EXPECT_TRUE(hidlReturn.isOk());
297 EXPECT_EQ(Result::OK, halResult);
298 EXPECT_EQ(radioClass, mHalProperties.classId);
299 EXPECT_GT(mHalProperties.numTuners, 0u);
300 if (radioClass == Class::AM_FM) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800301 EXPECT_GT(mHalProperties.bands.size(), 0u);
302 }
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700303
304 if (hidlReturn.isOk() && halResult == Result::OK) {
305 mHalPropertiesInitialized = true;
306 return true;
307 }
308 return false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800309}
310
311bool BroadcastRadioHidlTest::openTuner()
312{
313 if (!getProperties()) {
314 return false;
315 }
316 if (mTuner.get() == nullptr) {
317 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700318 auto openCb = [&](Result result, const sp<ITuner>& tuner) {
319 halResult = result;
320 if (result == Result::OK) {
321 mTuner = tuner;
322 }
323 };
324 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
Steven Morelandb6438422017-01-03 17:06:57 -0800325 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800326 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700327 if (radioClass == Class::AM_FM) {
328 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
329 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800330 }
331 EXPECT_NE(nullptr, mTuner.get());
332 return nullptr != mTuner.get();
333}
334
335bool BroadcastRadioHidlTest::checkAntenna()
336{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700337 if (radioClass != Class::AM_FM) return true;
338
Eric Laurent566fcda2016-11-23 10:36:36 -0800339 BandConfig halConfig;
340 Result halResult = Result::NOT_INITIALIZED;
341 Return<void> hidlReturn =
342 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
343 halResult = result;
344 if (result == Result::OK) {
345 halConfig = config;
346 }
347 });
348
349 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
350}
351
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700352BandConfig& BroadcastRadioHidlTest::getBand(unsigned idx) {
353 static BandConfig dummyBandConfig = {};
354 if (radioClass == Class::AM_FM) {
355 EXPECT_GT(mHalProperties.bands.size(), idx);
356 if (mHalProperties.bands.size() > idx) {
357 return mHalProperties.bands[idx];
358 } else {
359 return dummyBandConfig;
360 }
361 } else {
362 return dummyBandConfig;
363 }
364}
Eric Laurent566fcda2016-11-23 10:36:36 -0800365
366/**
367 * Test IBroadcastRadio::getProperties() method
368 *
369 * Verifies that:
370 * - the HAL implements the method
371 * - the method returns 0 (no error)
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700372 * - the implementation class is radioClass
Eric Laurent566fcda2016-11-23 10:36:36 -0800373 * - the implementation supports at least one tuner
374 * - the implementation supports at one band
375 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700376TEST_P(BroadcastRadioHidlTest, GetProperties) {
377 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800378 EXPECT_EQ(true, getProperties());
379}
380
381/**
382 * Test IBroadcastRadio::openTuner() method
383 *
384 * Verifies that:
385 * - the HAL implements the method
386 * - the method returns 0 (no error) and a valid ITuner interface
387 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700388TEST_P(BroadcastRadioHidlTest, OpenTuner) {
389 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800390 EXPECT_EQ(true, openTuner());
391}
392
393/**
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800394 * Test IBroadcastRadio::openTuner() after ITuner disposal.
395 *
396 * Verifies that:
397 * - ITuner destruction gets propagated through HAL
398 * - the openTuner method works well when called for the second time
399 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700400TEST_P(BroadcastRadioHidlTest, ReopenTuner) {
401 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800402 EXPECT_TRUE(openTuner());
403 mTuner.clear();
404 EXPECT_TRUE(openTuner());
405}
406
407/**
408 * Test IBroadcastRadio::openTuner() method called twice.
409 *
410 * Verifies that:
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700411 * - the openTuner method fails with INVALID_STATE or succeeds when called for the second time
412 * without deleting previous ITuner instance
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800413 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700414TEST_P(BroadcastRadioHidlTest, OpenTunerTwice) {
415 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800416 EXPECT_TRUE(openTuner());
417
418 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700419 auto openCb = [&](Result result, const sp<ITuner>&) { halResult = result; };
420 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800421 EXPECT_TRUE(hidlReturn.isOk());
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700422 if (halResult == Result::INVALID_STATE) {
423 EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
424 }
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800425}
426
427/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800428 * Test ITuner::setConfiguration() and getConfiguration methods
429 *
430 * Verifies that:
431 * - the HAL implements both methods
432 * - the methods return 0 (no error)
433 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
434 * - the configuration read back from HAl has the same class Id
435 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700436TEST_P(BroadcastRadioHidlTest, SetAndGetConfiguration) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700437 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700438 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800439 ASSERT_EQ(true, openTuner());
440 // test setConfiguration
441 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700442 Return<Result> hidlResult = mTuner->setConfiguration(getBand(1));
Steven Morelandb6438422017-01-03 17:06:57 -0800443 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800444 EXPECT_EQ(Result::OK, hidlResult);
445 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
446 EXPECT_EQ(Result::OK, mResultCallbackData);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700447 EXPECT_EQ(getBand(1), mBandConfigCallbackData);
Eric Laurent566fcda2016-11-23 10:36:36 -0800448
449 // test getConfiguration
450 BandConfig halConfig;
451 Result halResult;
452 Return<void> hidlReturn =
453 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
454 halResult = result;
455 if (result == Result::OK) {
456 halConfig = config;
457 }
458 });
Steven Morelandb6438422017-01-03 17:06:57 -0800459 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800460 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700461 EXPECT_EQ(getBand(1), halConfig);
Eric Laurent566fcda2016-11-23 10:36:36 -0800462}
463
464/**
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800465 * Test ITuner::setConfiguration() with invalid arguments.
466 *
467 * Verifies that:
468 * - the methods returns INVALID_ARGUMENTS on invalid arguments
469 * - the method recovers and succeeds after passing correct arguments
470 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700471TEST_P(BroadcastRadioHidlTest, SetConfigurationFails) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700472 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700473 RETURN_IF_SKIPPED;
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800474 ASSERT_EQ(true, openTuner());
475
476 // Let's define a config that's bad for sure.
477 BandConfig badConfig = {};
478 badConfig.type = Band::FM;
479 badConfig.lowerLimit = 0xFFFFFFFF;
480 badConfig.upperLimit = 0;
481 badConfig.spacings = (std::vector<uint32_t>){ 0 };
482
483 // Test setConfiguration failing on bad data.
484 mCallbackCalled = false;
485 auto setResult = mTuner->setConfiguration(badConfig);
486 EXPECT_TRUE(setResult.isOk());
487 EXPECT_EQ(Result::INVALID_ARGUMENTS, setResult);
488
489 // Test setConfiguration recovering after passing good data.
490 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700491 setResult = mTuner->setConfiguration(getBand(0));
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800492 EXPECT_TRUE(setResult.isOk());
493 EXPECT_EQ(Result::OK, setResult);
494 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
495 EXPECT_EQ(Result::OK, mResultCallbackData);
496}
497
498/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800499 * Test ITuner::scan
500 *
501 * Verifies that:
502 * - the HAL implements the method
503 * - the method returns 0 (no error)
504 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700505 * - skipping sub-channel or not does not fail the call
Eric Laurent566fcda2016-11-23 10:36:36 -0800506 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700507TEST_P(BroadcastRadioHidlTest, Scan) {
508 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800509 ASSERT_EQ(true, openTuner());
510 ASSERT_TRUE(checkAntenna());
511 // test scan UP
512 mCallbackCalled = false;
513 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800514 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800515 EXPECT_EQ(Result::OK, hidlResult);
516 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
517
518 // test scan DOWN
519 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700520 hidlResult = mTuner->scan(Direction::DOWN, false);
Steven Morelandb6438422017-01-03 17:06:57 -0800521 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800522 EXPECT_EQ(Result::OK, hidlResult);
523 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
524}
525
526/**
527 * Test ITuner::step
528 *
529 * Verifies that:
530 * - the HAL implements the method
531 * - the method returns 0 (no error)
532 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700533 * - skipping sub-channel or not does not fail the call
Eric Laurent566fcda2016-11-23 10:36:36 -0800534 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700535TEST_P(BroadcastRadioHidlTest, Step) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700536 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700537 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800538 ASSERT_EQ(true, openTuner());
539 ASSERT_TRUE(checkAntenna());
540 // test step UP
541 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700542 Return<Result> hidlResult = mTuner->step(Direction::UP, false);
Steven Morelandb6438422017-01-03 17:06:57 -0800543 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800544 EXPECT_EQ(Result::OK, hidlResult);
545 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
546
547 // test step DOWN
548 mCallbackCalled = false;
549 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800550 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800551 EXPECT_EQ(Result::OK, hidlResult);
552 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
553}
554
555/**
556 * Test ITuner::tune, getProgramInformation and cancel methods
557 *
558 * Verifies that:
559 * - the HAL implements the methods
560 * - the methods return 0 (no error)
561 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
562 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700563TEST_P(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700564 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700565 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800566 ASSERT_EQ(true, openTuner());
567 ASSERT_TRUE(checkAntenna());
568
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700569 auto& band = getBand(0);
570
Eric Laurent566fcda2016-11-23 10:36:36 -0800571 // test tune
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700572 ASSERT_GT(band.spacings.size(), 0u);
573 ASSERT_GT(band.upperLimit, band.lowerLimit);
Eric Laurent566fcda2016-11-23 10:36:36 -0800574
575 // test scan UP
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700576 uint32_t lowerLimit = band.lowerLimit;
577 uint32_t upperLimit = band.upperLimit;
578 uint32_t spacing = band.spacings[0];
Eric Laurent566fcda2016-11-23 10:36:36 -0800579
580 uint32_t channel =
581 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
582 mCallbackCalled = false;
583 mResultCallbackData = Result::NOT_INITIALIZED;
584 Return<Result> hidlResult = mTuner->tune(channel, 0);
Steven Morelandb6438422017-01-03 17:06:57 -0800585 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800586 EXPECT_EQ(Result::OK, hidlResult);
587 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800588 EXPECT_EQ(channel, mProgramInfoCallbackData.channel);
Eric Laurent566fcda2016-11-23 10:36:36 -0800589
590 // test getProgramInformation
591 ProgramInfo halInfo;
592 Result halResult = Result::NOT_INITIALIZED;
593 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800594 [&](Result result, const ProgramInfo& info) {
595 halResult = result;
596 if (result == Result::OK) {
597 halInfo = info;
598 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800599 });
Steven Morelandb6438422017-01-03 17:06:57 -0800600 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800601 EXPECT_EQ(Result::OK, halResult);
602 if (mResultCallbackData == Result::OK) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800603 EXPECT_LE(halInfo.channel, upperLimit);
604 EXPECT_GE(halInfo.channel, lowerLimit);
Eric Laurent566fcda2016-11-23 10:36:36 -0800605 }
606
607 // test cancel
608 mTuner->tune(lowerLimit, 0);
609 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800610 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800611 EXPECT_EQ(Result::OK, hidlResult);
612}
613
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800614/**
615 * Test ITuner::tune failing when channel out of the range is provided.
616 *
617 * Verifies that:
618 * - the method returns INVALID_ARGUMENTS when applicable
619 * - the method recovers and succeeds after passing correct arguments
620 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700621TEST_P(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700622 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700623 RETURN_IF_SKIPPED;
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800624 ASSERT_TRUE(openTuner());
625 ASSERT_TRUE(checkAntenna());
626
627 // get current channel bounds
628 BandConfig halConfig;
629 Result halResult;
630 auto configResult = mTuner->getConfiguration([&](Result result, const BandConfig& config) {
631 halResult = result;
632 halConfig = config;
633 });
634 ASSERT_TRUE(configResult.isOk());
635 ASSERT_EQ(Result::OK, halResult);
636
637 // try to tune slightly above the limit and expect to fail
638 auto badChannel = halConfig.upperLimit + halConfig.spacings[0];
639 auto tuneResult = mTuner->tune(badChannel, 0);
640 EXPECT_TRUE(tuneResult.isOk());
641 EXPECT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
642 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
643
644 // tuning exactly at the limit should succeed
645 auto goodChannel = halConfig.upperLimit;
646 tuneResult = mTuner->tune(goodChannel, 0);
647 EXPECT_TRUE(tuneResult.isOk());
648 EXPECT_EQ(Result::OK, tuneResult);
649 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
650}
651
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700652/**
653 * Test proper image format in metadata.
654 *
655 * Verifies that:
656 * - all images in metadata are provided in-band (as a binary blob, not by id)
657 *
658 * This is a counter-test for OobImagesOnly from 1.1 VTS.
659 */
660TEST_P(BroadcastRadioHidlTest, IbImagesOnly) {
661 RETURN_IF_SKIPPED;
662 ASSERT_TRUE(openTuner());
663 ASSERT_TRUE(checkAntenna());
664
665 bool firstScan = true;
666 uint32_t firstChannel, prevChannel;
667 while (true) {
668 mCallbackCalled = false;
669 auto hidlResult = mTuner->scan(Direction::UP, true);
670 ASSERT_TRUE(hidlResult.isOk());
671 if (hidlResult == Result::TIMEOUT) {
672 ALOGI("Got timeout on scan operation");
673 break;
674 }
675 ASSERT_EQ(Result::OK, hidlResult);
676 ASSERT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
677
678 if (firstScan) {
679 firstScan = false;
680 firstChannel = mProgramInfoCallbackData.channel;
681 } else {
682 // scanned the whole band
683 if (mProgramInfoCallbackData.channel >= firstChannel && prevChannel <= firstChannel) {
684 break;
685 }
686 }
687 prevChannel = mProgramInfoCallbackData.channel;
688
689 for (auto&& entry : mProgramInfoCallbackData.metadata) {
690 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
691 EXPECT_EQ(MetadataType::RAW, entry.type);
692 EXPECT_EQ(0, entry.intValue);
693 EXPECT_GT(entry.rawValue.size(), 0u);
694 }
695 }
696}
697
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700698INSTANTIATE_TEST_CASE_P(
699 BroadcastRadioHidlTestCases,
700 BroadcastRadioHidlTest,
701 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
Eric Laurent566fcda2016-11-23 10:36:36 -0800702
703int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800704 ::testing::InitGoogleTest(&argc, argv);
705 int status = RUN_ALL_TESTS();
706 ALOGI("Test result = %d", status);
707 return status;
708}