1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "broadcastradio.vts"
18
19 #include <VtsHalHidlTargetTestBase.h>
20 #include <android-base/logging.h>
21 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
22 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
23 #include <android/hardware/broadcastradio/1.1/ITuner.h>
24 #include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
25 #include <android/hardware/broadcastradio/1.1/types.h>
26 #include <broadcastradio-utils-1x/Utils.h>
27 #include <broadcastradio-vts-utils/call-barrier.h>
28 #include <broadcastradio-vts-utils/environment-utils.h>
29 #include <broadcastradio-vts-utils/mock-timeout.h>
30 #include <broadcastradio-vts-utils/pointer-utils.h>
31 #include <cutils/native_handle.h>
32 #include <cutils/properties.h>
33 #include <gmock/gmock.h>
34 #include <hidl/HidlTransportSupport.h>
35 #include <utils/threads.h>
36
37 #include <chrono>
38
39 namespace android {
40 namespace hardware {
41 namespace broadcastradio {
42 namespace V1_1 {
43 namespace vts {
44
45 using namespace std::chrono_literals;
46
47 using testing::_;
48 using testing::AnyNumber;
49 using testing::ByMove;
50 using testing::DoAll;
51 using testing::Invoke;
52 using testing::SaveArg;
53
54 using broadcastradio::vts::CallBarrier;
55 using V1_0::BandConfig;
56 using V1_0::Class;
57 using V1_0::MetaData;
58 using V1_0::MetadataKey;
59 using V1_0::MetadataType;
60
61 using broadcastradio::vts::clearAndWait;
62 using broadcastradio::vts::BroadcastRadioHidlEnvironment;
63
64 static constexpr auto kConfigTimeout = 10s;
65 static constexpr auto kConnectModuleTimeout = 1s;
66 static constexpr auto kTuneTimeout = 30s;
67 static constexpr auto kEventPropagationTimeout = 1s;
68 static constexpr auto kFullScanTimeout = 1min;
69
70 static constexpr ProgramType kStandardProgramTypes[] = {
71 ProgramType::AM, ProgramType::FM, ProgramType::AM_HD, ProgramType::FM_HD,
72 ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
73
printSkipped(std::string msg)74 static void printSkipped(std::string msg) {
75 std::cout << "[ SKIPPED ] " << msg << std::endl;
76 }
77
78 struct TunerCallbackMock : public ITunerCallback {
TunerCallbackMockandroid::hardware::broadcastradio::V1_1::vts::TunerCallbackMock79 TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
80
81 MOCK_METHOD0(hardwareFailure, Return<void>());
82 MOCK_TIMEOUT_METHOD2(configChange, Return<void>(Result, const BandConfig&));
83 MOCK_METHOD2(tuneComplete, Return<void>(Result, const V1_0::ProgramInfo&));
84 MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
85 MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
86 MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
87 MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
88 MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
89 MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
90 MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
91 MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
92 MOCK_METHOD0(programListChanged, Return<void>());
93 MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
94 };
95
96 static BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>* gEnv = nullptr;
97
98 class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
99 public ::testing::WithParamInterface<Class> {
100 protected:
101 virtual void SetUp() override;
102 virtual void TearDown() override;
103
104 bool openTuner();
105 bool nextBand();
106 bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
107
108 Class radioClass;
109 bool skipped = false;
110
111 sp<IBroadcastRadio> mRadioModule;
112 sp<ITuner> mTuner;
113 sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
114
115 private:
116 const BandConfig& getBand(unsigned idx);
117
118 unsigned currentBandIndex = 0;
119 hidl_vec<BandConfig> mBands;
120 };
121
SetUp()122 void BroadcastRadioHalTest::SetUp() {
123 radioClass = GetParam();
124
125 // lookup HIDL service
126 auto factory =
127 getService<IBroadcastRadioFactory>(gEnv->getServiceName<IBroadcastRadioFactory>());
128 ASSERT_NE(nullptr, factory.get());
129
130 // connect radio module
131 Result connectResult;
132 CallBarrier onConnect;
133 factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
134 connectResult = ret;
135 if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
136 onConnect.call();
137 });
138 ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
139
140 if (connectResult == Result::INVALID_ARGUMENTS) {
141 printSkipped("This device class is not supported.");
142 skipped = true;
143 return;
144 }
145 ASSERT_EQ(connectResult, Result::OK);
146 ASSERT_NE(nullptr, mRadioModule.get());
147
148 // get module properties
149 Properties prop11;
150 auto& prop10 = prop11.base;
151 auto propResult =
152 mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
153
154 ASSERT_TRUE(propResult.isOk());
155 EXPECT_EQ(radioClass, prop10.classId);
156 EXPECT_GT(prop10.numTuners, 0u);
157 EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
158 EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
159 if (radioClass == Class::AM_FM) {
160 EXPECT_GT(prop10.bands.size(), 0u);
161 }
162 mBands = prop10.bands;
163 }
164
TearDown()165 void BroadcastRadioHalTest::TearDown() {
166 mTuner.clear();
167 mRadioModule.clear();
168 clearAndWait(mCallback, 1s);
169 }
170
openTuner()171 bool BroadcastRadioHalTest::openTuner() {
172 EXPECT_EQ(nullptr, mTuner.get());
173
174 if (radioClass == Class::AM_FM) {
175 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
176 }
177
178 Result halResult = Result::NOT_INITIALIZED;
179 auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
180 halResult = result;
181 if (result != Result::OK) return;
182 mTuner = ITuner::castFrom(tuner);
183 };
184 currentBandIndex = 0;
185 auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
186
187 EXPECT_TRUE(hidlResult.isOk());
188 EXPECT_EQ(Result::OK, halResult);
189 EXPECT_NE(nullptr, mTuner.get());
190 if (radioClass == Class::AM_FM && mTuner != nullptr) {
191 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
192
193 BandConfig halConfig;
194 Result halResult = Result::NOT_INITIALIZED;
195 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
196 halResult = result;
197 halConfig = config;
198 });
199 EXPECT_EQ(Result::OK, halResult);
200 EXPECT_TRUE(halConfig.antennaConnected);
201 }
202
203 EXPECT_NE(nullptr, mTuner.get());
204 return nullptr != mTuner.get();
205 }
206
getBand(unsigned idx)207 const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
208 static const BandConfig dummyBandConfig = {};
209
210 if (radioClass != Class::AM_FM) {
211 ALOGD("Not AM/FM radio, returning dummy band config");
212 return dummyBandConfig;
213 }
214
215 EXPECT_GT(mBands.size(), idx);
216 if (mBands.size() <= idx) {
217 ALOGD("Band index out of bound, returning dummy band config");
218 return dummyBandConfig;
219 }
220
221 auto& band = mBands[idx];
222 ALOGD("Returning %s band", toString(band.type).c_str());
223 return band;
224 }
225
nextBand()226 bool BroadcastRadioHalTest::nextBand() {
227 if (currentBandIndex + 1 >= mBands.size()) return false;
228 currentBandIndex++;
229
230 BandConfig bandCb;
231 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
232 .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
233 auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
234 EXPECT_EQ(Result::OK, hidlResult);
235 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
236 EXPECT_EQ(getBand(currentBandIndex), bandCb);
237
238 return true;
239 }
240
getProgramList(std::function<void (const hidl_vec<ProgramInfo> & list)> cb)241 bool BroadcastRadioHalTest::getProgramList(
242 std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
243 ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
244 bool isListEmpty = true;
245 auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
246 ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
247 getListResult = result;
248 if (result != ProgramListResult::OK) return;
249 isListEmpty = (list.size() == 0);
250 if (!isListEmpty) cb(list);
251 };
252
253 // first try...
254 EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
255 .Times(AnyNumber());
256 auto hidlResult = mTuner->getProgramList({}, getListCb);
257 EXPECT_TRUE(hidlResult.isOk());
258 if (!hidlResult.isOk()) return false;
259
260 if (getListResult == ProgramListResult::NOT_STARTED) {
261 auto result = mTuner->startBackgroundScan();
262 EXPECT_EQ(ProgramListResult::OK, result);
263 getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
264 }
265 if (getListResult == ProgramListResult::NOT_READY) {
266 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
267
268 // second (last) try...
269 hidlResult = mTuner->getProgramList({}, getListCb);
270 EXPECT_TRUE(hidlResult.isOk());
271 if (!hidlResult.isOk()) return false;
272 EXPECT_EQ(ProgramListResult::OK, getListResult);
273 }
274
275 return !isListEmpty;
276 }
277
278 /**
279 * Test IBroadcastRadio::openTuner() method called twice.
280 *
281 * Verifies that:
282 * - the openTuner method succeeds when called for the second time without
283 * deleting previous ITuner instance.
284 *
285 * This is a more strict requirement than in 1.0, where a second openTuner
286 * might fail.
287 */
TEST_P(BroadcastRadioHalTest,OpenTunerTwice)288 TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
289 if (skipped) return;
290
291 ASSERT_TRUE(openTuner());
292
293 auto secondTuner = mTuner;
294 mTuner.clear();
295
296 ASSERT_TRUE(openTuner());
297 }
298
299 /**
300 * Test tuning to program list entry.
301 *
302 * Verifies that:
303 * - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
304 * - if the program list is NOT_STARTED, startBackgroundScan makes it completed
305 * within a full scan timeout and the next getProgramList call succeeds;
306 * - if the program list is not empty, tuneByProgramSelector call succeeds;
307 * - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
308 */
TEST_P(BroadcastRadioHalTest,TuneFromProgramList)309 TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
310 if (skipped) return;
311 ASSERT_TRUE(openTuner());
312
313 ProgramInfo firstProgram;
314 bool foundAny = false;
315 do {
316 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
317 // don't copy the whole list out, it might be heavy
318 firstProgram = list[0];
319 };
320 if (getProgramList(getCb)) foundAny = true;
321 } while (nextBand());
322 if (HasFailure()) return;
323 if (!foundAny) {
324 printSkipped("Program list is empty.");
325 return;
326 }
327
328 ProgramInfo infoCb;
329 ProgramSelector selCb;
330 EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
331 EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
332 .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
333 EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
334 .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
335 auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
336 ASSERT_EQ(Result::OK, tuneResult);
337 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
338 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
339 EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
340 EXPECT_EQ(infoCb.selector, selCb);
341
342 bool called = false;
343 auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
344 called = true;
345 EXPECT_EQ(Result::OK, result);
346 EXPECT_EQ(selCb, info.selector);
347 });
348 ASSERT_TRUE(getResult.isOk());
349 ASSERT_TRUE(called);
350 }
351
352 /**
353 * Test that primary vendor identifier isn't used for standard program types.
354 *
355 * Verifies that:
356 * - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
357 * identifier for program types other than VENDORn.
358 */
TEST_P(BroadcastRadioHalTest,TuneFailsForPrimaryVendor)359 TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
360 if (skipped) return;
361 ASSERT_TRUE(openTuner());
362
363 for (auto ptype : kStandardProgramTypes) {
364 ALOGD("Checking %s...", toString(ptype).c_str());
365 ProgramSelector sel = {};
366 sel.programType = static_cast<uint32_t>(ptype);
367 sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
368
369 auto tuneResult = mTuner->tuneByProgramSelector(sel);
370 ASSERT_NE(Result::OK, tuneResult);
371 }
372 }
373
374 /**
375 * Test that tune with unknown program type fails.
376 *
377 * Verifies that:
378 * - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
379 */
TEST_P(BroadcastRadioHalTest,TuneFailsForUnknownProgram)380 TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
381 if (skipped) return;
382 ASSERT_TRUE(openTuner());
383
384 // Program type is 1-based, so 0 will be always invalid.
385 ProgramSelector sel = {};
386 auto tuneResult = mTuner->tuneByProgramSelector(sel);
387 ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
388 }
389
390 /**
391 * Test cancelling announcement.
392 *
393 * Verifies that:
394 * - cancelAnnouncement succeeds either when there is an announcement or there is none.
395 */
TEST_P(BroadcastRadioHalTest,CancelAnnouncement)396 TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
397 if (skipped) return;
398 ASSERT_TRUE(openTuner());
399
400 auto hidlResult = mTuner->cancelAnnouncement();
401 EXPECT_EQ(Result::OK, hidlResult);
402 }
403
404 /**
405 * Test getImage call with invalid image ID.
406 *
407 * Verifies that:
408 * - getImage call handles argument 0 gracefully.
409 */
TEST_P(BroadcastRadioHalTest,GetNoImage)410 TEST_P(BroadcastRadioHalTest, GetNoImage) {
411 if (skipped) return;
412
413 size_t len = 0;
414 auto hidlResult =
415 mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
416
417 ASSERT_TRUE(hidlResult.isOk());
418 ASSERT_EQ(0u, len);
419 }
420
421 /**
422 * Test proper image format in metadata.
423 *
424 * Verifies that:
425 * - all images in metadata are provided out-of-band (by id, not as a binary blob);
426 * - images are available for getImage call.
427 */
TEST_P(BroadcastRadioHalTest,OobImagesOnly)428 TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
429 if (skipped) return;
430 ASSERT_TRUE(openTuner());
431
432 std::vector<int> imageIds;
433
434 do {
435 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
436 for (auto&& program : list) {
437 for (auto&& entry : program.base.metadata) {
438 EXPECT_NE(MetadataType::RAW, entry.type);
439 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
440 EXPECT_NE(0, entry.intValue);
441 EXPECT_EQ(0u, entry.rawValue.size());
442 if (entry.intValue != 0) imageIds.push_back(entry.intValue);
443 }
444 }
445 };
446 getProgramList(getCb);
447 } while (nextBand());
448
449 if (imageIds.size() == 0) {
450 printSkipped("No images found");
451 return;
452 }
453
454 for (auto id : imageIds) {
455 ALOGD("Checking image %d", id);
456
457 size_t len = 0;
458 auto hidlResult =
459 mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
460
461 ASSERT_TRUE(hidlResult.isOk());
462 ASSERT_GT(len, 0u);
463 }
464 }
465
466 /**
467 * Test AnalogForced switch.
468 *
469 * Verifies that:
470 * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
471 */
TEST_P(BroadcastRadioHalTest,AnalogForcedSwitch)472 TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
473 if (skipped) return;
474 ASSERT_TRUE(openTuner());
475
476 bool forced;
477 Result halIsResult;
478 auto isCb = [&](Result result, bool isForced) {
479 halIsResult = result;
480 forced = isForced;
481 };
482
483 // set analog mode
484 auto setResult = mTuner->setAnalogForced(true);
485 ASSERT_TRUE(setResult.isOk());
486 if (Result::INVALID_STATE == setResult) {
487 // if setter fails, getter should fail too - it means the switch is not supported at all
488 auto isResult = mTuner->isAnalogForced(isCb);
489 ASSERT_TRUE(isResult.isOk());
490 EXPECT_EQ(Result::INVALID_STATE, halIsResult);
491 return;
492 }
493 ASSERT_EQ(Result::OK, setResult);
494
495 // check, if it's analog
496 auto isResult = mTuner->isAnalogForced(isCb);
497 ASSERT_TRUE(isResult.isOk());
498 EXPECT_EQ(Result::OK, halIsResult);
499 ASSERT_TRUE(forced);
500
501 // set digital mode
502 setResult = mTuner->setAnalogForced(false);
503 ASSERT_EQ(Result::OK, setResult);
504
505 // check, if it's digital
506 isResult = mTuner->isAnalogForced(isCb);
507 ASSERT_TRUE(isResult.isOk());
508 EXPECT_EQ(Result::OK, halIsResult);
509 ASSERT_FALSE(forced);
510 }
511
verifyIdentifier(const ProgramIdentifier & id)512 static void verifyIdentifier(const ProgramIdentifier& id) {
513 EXPECT_NE(id.type, 0u);
514 auto val = id.value;
515
516 switch (static_cast<IdentifierType>(id.type)) {
517 case IdentifierType::AMFM_FREQUENCY:
518 case IdentifierType::DAB_FREQUENCY:
519 case IdentifierType::DRMO_FREQUENCY:
520 EXPECT_GT(val, 100u) << "Expected f > 100kHz";
521 EXPECT_LT(val, 10000000u) << "Expected f < 10GHz";
522 break;
523 case IdentifierType::RDS_PI:
524 EXPECT_GT(val, 0u);
525 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
526 break;
527 case IdentifierType::HD_STATION_ID_EXT: {
528 auto stationId = val & 0xFFFFFFFF; // 32bit
529 val >>= 32;
530 auto subchannel = val & 0xF; // 4bit
531 val >>= 4;
532 auto freq = val & 0x3FFFF; // 18bit
533 EXPECT_GT(stationId, 0u);
534 EXPECT_LT(subchannel, 8u) << "Expected ch < 8";
535 EXPECT_GT(freq, 100u) << "Expected f > 100kHz";
536 EXPECT_LT(freq, 10000000u) << "Expected f < 10GHz";
537 break;
538 }
539 case IdentifierType::HD_SUBCHANNEL:
540 EXPECT_LT(val, 8u) << "Expected ch < 8";
541 break;
542 case IdentifierType::DAB_SIDECC: {
543 auto sid = val & 0xFFFF; // 16bit
544 val >>= 16;
545 auto ecc = val & 0xFF; // 8bit
546 EXPECT_NE(sid, 0u);
547 EXPECT_GE(ecc, 0xA0u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
548 EXPECT_LE(ecc, 0xF6u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
549 break;
550 }
551 case IdentifierType::DAB_ENSEMBLE:
552 EXPECT_GT(val, 0u);
553 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
554 break;
555 case IdentifierType::DAB_SCID:
556 EXPECT_GT(val, 0xFu) << "Expected 12bit SCId (not 4bit SCIdS)";
557 EXPECT_LE(val, 0xFFFu) << "Expected 12bit id";
558 break;
559 case IdentifierType::DRMO_SERVICE_ID:
560 EXPECT_GT(val, 0u);
561 EXPECT_LE(val, 0xFFFFFFu) << "Expected 24bit id";
562 break;
563 case IdentifierType::DRMO_MODULATION:
564 EXPECT_GE(val, static_cast<uint32_t>(Modulation::AM));
565 EXPECT_LE(val, static_cast<uint32_t>(Modulation::FM));
566 break;
567 case IdentifierType::SXM_SERVICE_ID:
568 EXPECT_GT(val, 0u);
569 EXPECT_LE(val, 0xFFFFFFFFu) << "Expected 32bit id";
570 break;
571 case IdentifierType::SXM_CHANNEL:
572 EXPECT_LT(val, 1000u);
573 break;
574 case IdentifierType::VENDOR_PRIMARY_START:
575 case IdentifierType::VENDOR_PRIMARY_END:
576 // skip
577 break;
578 }
579 }
580
581 /**
582 * Test ProgramIdentifier format.
583 *
584 * Verifies that:
585 * - values of ProgramIdentifier match their definitions at IdentifierType.
586 */
TEST_P(BroadcastRadioHalTest,VerifyIdentifiersFormat)587 TEST_P(BroadcastRadioHalTest, VerifyIdentifiersFormat) {
588 if (skipped) return;
589 ASSERT_TRUE(openTuner());
590
591 do {
592 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
593 for (auto&& program : list) {
594 verifyIdentifier(program.selector.primaryId);
595 for (auto&& id : program.selector.secondaryIds) {
596 verifyIdentifier(id);
597 }
598 }
599 };
600 getProgramList(getCb);
601 } while (nextBand());
602 }
603
604 INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
605 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
606
607 } // namespace vts
608 } // namespace V1_1
609 } // namespace broadcastradio
610 } // namespace hardware
611 } // namespace android
612
main(int argc,char ** argv)613 int main(int argc, char** argv) {
614 using android::hardware::broadcastradio::V1_1::vts::gEnv;
615 using android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
616 using android::hardware::broadcastradio::vts::BroadcastRadioHidlEnvironment;
617 gEnv = new BroadcastRadioHidlEnvironment<IBroadcastRadioFactory>;
618 ::testing::AddGlobalTestEnvironment(gEnv);
619 ::testing::InitGoogleTest(&argc, argv);
620 gEnv->init(&argc, argv);
621 int status = RUN_ALL_TESTS();
622 ALOGI("Test result = %d", status);
623 return status;
624 }
625