blob: fd048db35d41b6c96ed78b4385a9c61ee8c2ab46 [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 Wasilczyk394b3432017-08-07 18:00:28 -0700232
233 /**
234 * Retrieves AM/FM band configuration from module properties.
235 *
236 * The configuration may not exist: if radio type is other than AM/FM
237 * or provided index is out of bounds.
238 * In such case, empty configuration is returned.
239 *
240 * @param idx Band index to retrieve.
241 * @return Band configuration reference.
242 */
243 const BandConfig& getBand(unsigned idx);
Eric Laurent566fcda2016-11-23 10:36:36 -0800244
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700245 static const nsecs_t kConnectCallbacktimeoutNs = seconds_to_nanoseconds(1);
Eric Laurent566fcda2016-11-23 10:36:36 -0800246 static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
247 static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
248
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700249 Class radioClass;
250 bool skipped;
Eric Laurent566fcda2016-11-23 10:36:36 -0800251 sp<IBroadcastRadio> mRadio;
252 Properties mHalProperties;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700253 bool mHalPropertiesInitialized = false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800254 sp<ITuner> mTuner;
255 sp<MyCallback> mTunerCallback;
256 Mutex mLock;
257 Condition mCallbackCond;
258 bool mCallbackCalled;
259 bool mBoolCallbackData;
260 Result mResultCallbackData;
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800261 ProgramInfo mProgramInfoCallbackData;
262 BandConfig mBandConfigCallbackData;
Eric Laurent566fcda2016-11-23 10:36:36 -0800263 bool mHwFailure;
264};
265
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800266namespace android {
267namespace hardware {
268namespace broadcastradio {
269namespace V1_0 {
270
271/**
272 * Compares two BandConfig objects for testing purposes.
273 */
274static bool operator==(const BandConfig& l, const BandConfig& r) {
275 if (l.type != r.type) return false;
276 if (l.antennaConnected != r.antennaConnected) return false;
277 if (l.lowerLimit != r.lowerLimit) return false;
278 if (l.upperLimit != r.upperLimit) return false;
279 if (l.spacings != r.spacings) return false;
280 if (l.type == Band::AM || l.type == Band::AM_HD) {
281 return l.ext.am == r.ext.am;
282 } else if (l.type == Band::FM || l.type == Band::FM_HD) {
283 return l.ext.fm == r.ext.fm;
284 } else {
285 // unsupported type
286 return false;
287 }
288}
289
290} // V1_0
291} // broadcastradio
292} // hardware
293} // android
294
Eric Laurent566fcda2016-11-23 10:36:36 -0800295bool BroadcastRadioHidlTest::getProperties()
296{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700297 if (mHalPropertiesInitialized) return true;
Eric Laurent566fcda2016-11-23 10:36:36 -0800298
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700299 Result halResult = Result::NOT_INITIALIZED;
300 auto hidlReturn = mRadio->getProperties([&](Result result, const Properties& properties) {
301 halResult = result;
302 if (result == Result::OK) {
303 mHalProperties = properties;
304 }
305 });
306
307 EXPECT_TRUE(hidlReturn.isOk());
308 EXPECT_EQ(Result::OK, halResult);
309 EXPECT_EQ(radioClass, mHalProperties.classId);
310 EXPECT_GT(mHalProperties.numTuners, 0u);
311 if (radioClass == Class::AM_FM) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800312 EXPECT_GT(mHalProperties.bands.size(), 0u);
313 }
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700314
315 if (hidlReturn.isOk() && halResult == Result::OK) {
316 mHalPropertiesInitialized = true;
317 return true;
318 }
319 return false;
Eric Laurent566fcda2016-11-23 10:36:36 -0800320}
321
322bool BroadcastRadioHidlTest::openTuner()
323{
324 if (!getProperties()) {
325 return false;
326 }
327 if (mTuner.get() == nullptr) {
328 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700329 auto openCb = [&](Result result, const sp<ITuner>& tuner) {
330 halResult = result;
331 if (result == Result::OK) {
332 mTuner = tuner;
333 }
334 };
335 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
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);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700338 if (radioClass == Class::AM_FM) {
339 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
340 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800341 }
342 EXPECT_NE(nullptr, mTuner.get());
343 return nullptr != mTuner.get();
344}
345
346bool BroadcastRadioHidlTest::checkAntenna()
347{
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700348 if (radioClass != Class::AM_FM) return true;
349
Eric Laurent566fcda2016-11-23 10:36:36 -0800350 BandConfig halConfig;
351 Result halResult = Result::NOT_INITIALIZED;
352 Return<void> hidlReturn =
353 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
354 halResult = result;
355 if (result == Result::OK) {
356 halConfig = config;
357 }
358 });
359
360 return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
361}
362
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700363const BandConfig& BroadcastRadioHidlTest::getBand(unsigned idx) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700364 static BandConfig dummyBandConfig = {};
365 if (radioClass == Class::AM_FM) {
366 EXPECT_GT(mHalProperties.bands.size(), idx);
367 if (mHalProperties.bands.size() > idx) {
368 return mHalProperties.bands[idx];
369 } else {
370 return dummyBandConfig;
371 }
372 } else {
373 return dummyBandConfig;
374 }
375}
Eric Laurent566fcda2016-11-23 10:36:36 -0800376
377/**
378 * Test IBroadcastRadio::getProperties() method
379 *
380 * Verifies that:
381 * - the HAL implements the method
382 * - the method returns 0 (no error)
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700383 * - the implementation class is radioClass
Eric Laurent566fcda2016-11-23 10:36:36 -0800384 * - the implementation supports at least one tuner
385 * - the implementation supports at one band
386 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700387TEST_P(BroadcastRadioHidlTest, GetProperties) {
388 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800389 EXPECT_EQ(true, getProperties());
390}
391
392/**
393 * Test IBroadcastRadio::openTuner() method
394 *
395 * Verifies that:
396 * - the HAL implements the method
397 * - the method returns 0 (no error) and a valid ITuner interface
398 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700399TEST_P(BroadcastRadioHidlTest, OpenTuner) {
400 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800401 EXPECT_EQ(true, openTuner());
402}
403
404/**
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800405 * Test IBroadcastRadio::openTuner() after ITuner disposal.
406 *
407 * Verifies that:
408 * - ITuner destruction gets propagated through HAL
409 * - the openTuner method works well when called for the second time
410 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700411TEST_P(BroadcastRadioHidlTest, ReopenTuner) {
412 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800413 EXPECT_TRUE(openTuner());
414 mTuner.clear();
415 EXPECT_TRUE(openTuner());
416}
417
418/**
419 * Test IBroadcastRadio::openTuner() method called twice.
420 *
421 * Verifies that:
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700422 * - the openTuner method fails with INVALID_STATE or succeeds when called for the second time
423 * without deleting previous ITuner instance
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800424 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700425TEST_P(BroadcastRadioHidlTest, OpenTunerTwice) {
426 RETURN_IF_SKIPPED;
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800427 EXPECT_TRUE(openTuner());
428
429 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700430 auto openCb = [&](Result result, const sp<ITuner>&) { halResult = result; };
431 auto hidlReturn = mRadio->openTuner(getBand(0), true, mTunerCallback, openCb);
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800432 EXPECT_TRUE(hidlReturn.isOk());
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700433 if (halResult == Result::OK) {
434 if (radioClass == Class::AM_FM) {
435 EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
436 }
437 } else {
438 EXPECT_EQ(Result::INVALID_STATE, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700439 }
Tomasz Wasilczykbe71e9c2016-12-22 11:49:17 -0800440}
441
442/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800443 * Test ITuner::setConfiguration() and getConfiguration methods
444 *
445 * Verifies that:
446 * - the HAL implements both methods
447 * - the methods return 0 (no error)
448 * - the configuration callback is received within kConfigCallbacktimeoutNs ns
449 * - the configuration read back from HAl has the same class Id
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700450 *
451 * Skipped for other radio classes than AM/FM, because setConfiguration
452 * applies only for these bands.
Eric Laurent566fcda2016-11-23 10:36:36 -0800453 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700454TEST_P(BroadcastRadioHidlTest, SetAndGetConfiguration) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700455 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700456 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800457 ASSERT_EQ(true, openTuner());
458 // test setConfiguration
459 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700460 Return<Result> hidlResult = mTuner->setConfiguration(getBand(1));
Steven Morelandb6438422017-01-03 17:06:57 -0800461 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800462 EXPECT_EQ(Result::OK, hidlResult);
463 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
464 EXPECT_EQ(Result::OK, mResultCallbackData);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700465 EXPECT_EQ(getBand(1), mBandConfigCallbackData);
Eric Laurent566fcda2016-11-23 10:36:36 -0800466
467 // test getConfiguration
468 BandConfig halConfig;
469 Result halResult;
470 Return<void> hidlReturn =
471 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
472 halResult = result;
473 if (result == Result::OK) {
474 halConfig = config;
475 }
476 });
Steven Morelandb6438422017-01-03 17:06:57 -0800477 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800478 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700479 EXPECT_EQ(getBand(1), halConfig);
Eric Laurent566fcda2016-11-23 10:36:36 -0800480}
481
482/**
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800483 * Test ITuner::setConfiguration() with invalid arguments.
484 *
485 * Verifies that:
486 * - the methods returns INVALID_ARGUMENTS on invalid arguments
487 * - the method recovers and succeeds after passing correct arguments
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700488 *
489 * Skipped for other radio classes than AM/FM, because setConfiguration
490 * applies only for these bands.
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800491 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700492TEST_P(BroadcastRadioHidlTest, SetConfigurationFails) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700493 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700494 RETURN_IF_SKIPPED;
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800495 ASSERT_EQ(true, openTuner());
496
497 // Let's define a config that's bad for sure.
498 BandConfig badConfig = {};
499 badConfig.type = Band::FM;
500 badConfig.lowerLimit = 0xFFFFFFFF;
501 badConfig.upperLimit = 0;
502 badConfig.spacings = (std::vector<uint32_t>){ 0 };
503
504 // Test setConfiguration failing on bad data.
505 mCallbackCalled = false;
506 auto setResult = mTuner->setConfiguration(badConfig);
507 EXPECT_TRUE(setResult.isOk());
508 EXPECT_EQ(Result::INVALID_ARGUMENTS, setResult);
509
510 // Test setConfiguration recovering after passing good data.
511 mCallbackCalled = false;
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700512 setResult = mTuner->setConfiguration(getBand(0));
Tomasz Wasilczyk10877cd2017-03-07 17:04:26 -0800513 EXPECT_TRUE(setResult.isOk());
514 EXPECT_EQ(Result::OK, setResult);
515 EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
516 EXPECT_EQ(Result::OK, mResultCallbackData);
517}
518
519/**
Eric Laurent566fcda2016-11-23 10:36:36 -0800520 * Test ITuner::scan
521 *
522 * Verifies that:
523 * - the HAL implements the method
524 * - the method returns 0 (no error)
525 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700526 * - skipping sub-channel or not does not fail the call
Eric Laurent566fcda2016-11-23 10:36:36 -0800527 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700528TEST_P(BroadcastRadioHidlTest, Scan) {
529 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800530 ASSERT_EQ(true, openTuner());
531 ASSERT_TRUE(checkAntenna());
532 // test scan UP
533 mCallbackCalled = false;
534 Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800535 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800536 EXPECT_EQ(Result::OK, hidlResult);
537 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
538
539 // test scan DOWN
540 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700541 hidlResult = mTuner->scan(Direction::DOWN, 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
547/**
548 * Test ITuner::step
549 *
550 * Verifies that:
551 * - the HAL implements the method
552 * - the method returns 0 (no error)
553 * - the tuned callback is received within kTuneCallbacktimeoutNs ns
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700554 * - skipping sub-channel or not does not fail the call
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700555 *
556 * Skipped for other radio classes than AM/FM, because step is not possible
557 * on DAB nor satellite.
Eric Laurent566fcda2016-11-23 10:36:36 -0800558 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700559TEST_P(BroadcastRadioHidlTest, Step) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700560 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700561 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800562 ASSERT_EQ(true, openTuner());
563 ASSERT_TRUE(checkAntenna());
564 // test step UP
565 mCallbackCalled = false;
Tomasz Wasilczyka8dec0f2017-03-14 10:20:53 -0700566 Return<Result> hidlResult = mTuner->step(Direction::UP, false);
Steven Morelandb6438422017-01-03 17:06:57 -0800567 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800568 EXPECT_EQ(Result::OK, hidlResult);
569 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
570
571 // test step DOWN
572 mCallbackCalled = false;
573 hidlResult = mTuner->step(Direction::DOWN, true);
Steven Morelandb6438422017-01-03 17:06:57 -0800574 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800575 EXPECT_EQ(Result::OK, hidlResult);
576 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
577}
578
579/**
580 * Test ITuner::tune, getProgramInformation and cancel methods
581 *
582 * Verifies that:
583 * - the HAL implements the methods
584 * - the methods return 0 (no error)
585 * - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700586 *
587 * Skipped for other radio classes than AM/FM, because tune to frequency
588 * is not possible on DAB nor satellite.
Eric Laurent566fcda2016-11-23 10:36:36 -0800589 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700590TEST_P(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700591 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700592 RETURN_IF_SKIPPED;
Eric Laurent566fcda2016-11-23 10:36:36 -0800593 ASSERT_EQ(true, openTuner());
594 ASSERT_TRUE(checkAntenna());
595
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700596 auto& band = getBand(0);
597
Eric Laurent566fcda2016-11-23 10:36:36 -0800598 // test tune
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700599 ASSERT_GT(band.spacings.size(), 0u);
600 ASSERT_GT(band.upperLimit, band.lowerLimit);
Eric Laurent566fcda2016-11-23 10:36:36 -0800601
602 // test scan UP
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700603 uint32_t lowerLimit = band.lowerLimit;
604 uint32_t upperLimit = band.upperLimit;
605 uint32_t spacing = band.spacings[0];
Eric Laurent566fcda2016-11-23 10:36:36 -0800606
607 uint32_t channel =
608 lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
609 mCallbackCalled = false;
610 mResultCallbackData = Result::NOT_INITIALIZED;
611 Return<Result> hidlResult = mTuner->tune(channel, 0);
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 EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
Tomasz Wasilczykf3c036d2017-03-03 15:07:50 -0800615 EXPECT_EQ(channel, mProgramInfoCallbackData.channel);
Eric Laurent566fcda2016-11-23 10:36:36 -0800616
617 // test getProgramInformation
618 ProgramInfo halInfo;
619 Result halResult = Result::NOT_INITIALIZED;
620 Return<void> hidlReturn = mTuner->getProgramInformation(
Tomasz Wasilczyk5cc9d862017-01-06 14:19:11 -0800621 [&](Result result, const ProgramInfo& info) {
622 halResult = result;
623 if (result == Result::OK) {
624 halInfo = info;
625 }
Eric Laurent566fcda2016-11-23 10:36:36 -0800626 });
Steven Morelandb6438422017-01-03 17:06:57 -0800627 EXPECT_TRUE(hidlReturn.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800628 EXPECT_EQ(Result::OK, halResult);
629 if (mResultCallbackData == Result::OK) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800630 EXPECT_LE(halInfo.channel, upperLimit);
631 EXPECT_GE(halInfo.channel, lowerLimit);
Eric Laurent566fcda2016-11-23 10:36:36 -0800632 }
633
634 // test cancel
635 mTuner->tune(lowerLimit, 0);
636 hidlResult = mTuner->cancel();
Steven Morelandb6438422017-01-03 17:06:57 -0800637 EXPECT_TRUE(hidlResult.isOk());
Eric Laurent566fcda2016-11-23 10:36:36 -0800638 EXPECT_EQ(Result::OK, hidlResult);
639}
640
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800641/**
642 * Test ITuner::tune failing when channel out of the range is provided.
643 *
644 * Verifies that:
645 * - the method returns INVALID_ARGUMENTS when applicable
646 * - the method recovers and succeeds after passing correct arguments
Tomasz Wasilczyk394b3432017-08-07 18:00:28 -0700647 *
648 * Skipped for other radio classes than AM/FM, because tune to frequency
649 * is not possible on DAB nor satellite.
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800650 */
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700651TEST_P(BroadcastRadioHidlTest, TuneFailsOutOfBounds) {
Tomasz Wasilczykda72d372017-06-26 16:08:51 -0700652 if (radioClass != Class::AM_FM) skipped = true;
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700653 RETURN_IF_SKIPPED;
Tomasz Wasilczyk59d985d2017-03-03 13:02:15 -0800654 ASSERT_TRUE(openTuner());
655 ASSERT_TRUE(checkAntenna());
656
657 // get current channel bounds
658 BandConfig halConfig;
659 Result halResult;
660 auto configResult = mTuner->getConfiguration([&](Result result, const BandConfig& config) {
661 halResult = result;
662 halConfig = config;
663 });
664 ASSERT_TRUE(configResult.isOk());
665 ASSERT_EQ(Result::OK, halResult);
666
667 // try to tune slightly above the limit and expect to fail
668 auto badChannel = halConfig.upperLimit + halConfig.spacings[0];
669 auto tuneResult = mTuner->tune(badChannel, 0);
670 EXPECT_TRUE(tuneResult.isOk());
671 EXPECT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
672 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
673
674 // tuning exactly at the limit should succeed
675 auto goodChannel = halConfig.upperLimit;
676 tuneResult = mTuner->tune(goodChannel, 0);
677 EXPECT_TRUE(tuneResult.isOk());
678 EXPECT_EQ(Result::OK, tuneResult);
679 EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
680}
681
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700682/**
683 * Test proper image format in metadata.
684 *
685 * Verifies that:
686 * - all images in metadata are provided in-band (as a binary blob, not by id)
687 *
688 * This is a counter-test for OobImagesOnly from 1.1 VTS.
689 */
690TEST_P(BroadcastRadioHidlTest, IbImagesOnly) {
691 RETURN_IF_SKIPPED;
692 ASSERT_TRUE(openTuner());
693 ASSERT_TRUE(checkAntenna());
694
695 bool firstScan = true;
696 uint32_t firstChannel, prevChannel;
697 while (true) {
698 mCallbackCalled = false;
699 auto hidlResult = mTuner->scan(Direction::UP, true);
700 ASSERT_TRUE(hidlResult.isOk());
701 if (hidlResult == Result::TIMEOUT) {
702 ALOGI("Got timeout on scan operation");
703 break;
704 }
705 ASSERT_EQ(Result::OK, hidlResult);
706 ASSERT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
707
708 if (firstScan) {
709 firstScan = false;
710 firstChannel = mProgramInfoCallbackData.channel;
711 } else {
712 // scanned the whole band
713 if (mProgramInfoCallbackData.channel >= firstChannel && prevChannel <= firstChannel) {
714 break;
715 }
716 }
717 prevChannel = mProgramInfoCallbackData.channel;
718
719 for (auto&& entry : mProgramInfoCallbackData.metadata) {
720 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
721 EXPECT_EQ(MetadataType::RAW, entry.type);
722 EXPECT_EQ(0, entry.intValue);
723 EXPECT_GT(entry.rawValue.size(), 0u);
724 }
725 }
726}
727
Tomasz Wasilczyk2f461012017-03-14 11:19:15 -0700728INSTANTIATE_TEST_CASE_P(
729 BroadcastRadioHidlTestCases,
730 BroadcastRadioHidlTest,
731 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
Eric Laurent566fcda2016-11-23 10:36:36 -0800732
733int main(int argc, char** argv) {
Eric Laurent566fcda2016-11-23 10:36:36 -0800734 ::testing::InitGoogleTest(&argc, argv);
735 int status = RUN_ALL_TESTS();
736 ALOGI("Test result = %d", status);
737 return status;
738}