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