blob: 823d14c44e35fc7c168850f23e0d9786b1a5c283 [file] [log] [blame]
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -08001/*
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
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070017#define LOG_TAG "broadcastradio.vts"
18
Yuexi Maed2bb4e2017-03-10 00:44:45 -080019#include <VtsHalHidlTargetTestBase.h>
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -080020#include <android-base/logging.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070021#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>
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -080026#include <broadcastradio-utils-1x/Utils.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070027#include <broadcastradio-vts-utils/call-barrier.h>
28#include <broadcastradio-vts-utils/mock-timeout.h>
Tomasz Wasilczyk31e86322017-12-05 09:36:11 -080029#include <broadcastradio-vts-utils/pointer-utils.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080030#include <cutils/native_handle.h>
31#include <cutils/properties.h>
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070032#include <gmock/gmock.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080033#include <hidl/HidlTransportSupport.h>
34#include <utils/threads.h>
35
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070036#include <chrono>
37
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070038namespace android {
39namespace hardware {
40namespace broadcastradio {
41namespace V1_1 {
42namespace vts {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080043
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070044using namespace std::chrono_literals;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080045
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070046using testing::_;
47using testing::AnyNumber;
48using testing::ByMove;
49using testing::DoAll;
Tomasz Wasilczyk24180092017-07-14 10:44:52 -070050using testing::Invoke;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070051using testing::SaveArg;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080052
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070053using broadcastradio::vts::CallBarrier;
54using V1_0::BandConfig;
55using V1_0::Class;
56using V1_0::MetaData;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -070057using V1_0::MetadataKey;
58using V1_0::MetadataType;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080059
Tomasz Wasilczyk31e86322017-12-05 09:36:11 -080060using broadcastradio::vts::clearAndWait;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070061
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070062static constexpr auto kConfigTimeout = 10s;
63static constexpr auto kConnectModuleTimeout = 1s;
64static constexpr auto kTuneTimeout = 30s;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -070065static constexpr auto kEventPropagationTimeout = 1s;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070066static constexpr auto kFullScanTimeout = 1min;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080067
Tomasz Wasilczykdd587702017-07-31 14:28:04 -070068static constexpr ProgramType kStandardProgramTypes[] = {
69 ProgramType::AM, ProgramType::FM, ProgramType::AM_HD, ProgramType::FM_HD,
70 ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
71
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070072static void printSkipped(std::string msg) {
73 std::cout << "[ SKIPPED ] " << msg << std::endl;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080074}
75
Tomasz Wasilczyk24180092017-07-14 10:44:52 -070076struct TunerCallbackMock : public ITunerCallback {
77 TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
78
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070079 MOCK_METHOD0(hardwareFailure, Return<void>());
80 MOCK_TIMEOUT_METHOD2(configChange, Return<void>(Result, const BandConfig&));
81 MOCK_METHOD2(tuneComplete, Return<void>(Result, const V1_0::ProgramInfo&));
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -070082 MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070083 MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070084 MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
85 MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
86 MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
87 MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
88 MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
89 MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
90 MOCK_METHOD0(programListChanged, Return<void>());
Tomasz Wasilczykdd130662017-08-03 18:08:57 -070091 MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070092};
93
94class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
95 public ::testing::WithParamInterface<Class> {
96 protected:
97 virtual void SetUp() override;
98 virtual void TearDown() override;
99
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700100 bool openTuner();
101 bool nextBand();
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700102 bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700103
104 Class radioClass;
105 bool skipped = false;
106
107 sp<IBroadcastRadio> mRadioModule;
108 sp<ITuner> mTuner;
109 sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
110
111 private:
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700112 const BandConfig& getBand(unsigned idx);
113
114 unsigned currentBandIndex = 0;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700115 hidl_vec<BandConfig> mBands;
116};
117
118void BroadcastRadioHalTest::SetUp() {
119 radioClass = GetParam();
120
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700121 // lookup HIDL service
122 auto factory = getService<IBroadcastRadioFactory>();
123 ASSERT_NE(nullptr, factory.get());
124
125 // connect radio module
126 Result connectResult;
127 CallBarrier onConnect;
128 factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
129 connectResult = ret;
130 if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
131 onConnect.call();
132 });
133 ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
134
135 if (connectResult == Result::INVALID_ARGUMENTS) {
136 printSkipped("This device class is not supported.");
137 skipped = true;
138 return;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800139 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700140 ASSERT_EQ(connectResult, Result::OK);
141 ASSERT_NE(nullptr, mRadioModule.get());
142
143 // get module properties
144 Properties prop11;
145 auto& prop10 = prop11.base;
146 auto propResult =
147 mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
148
149 ASSERT_TRUE(propResult.isOk());
150 EXPECT_EQ(radioClass, prop10.classId);
151 EXPECT_GT(prop10.numTuners, 0u);
Tomasz Wasilczyke192c392017-07-16 15:14:34 -0700152 EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
153 EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700154 if (radioClass == Class::AM_FM) {
155 EXPECT_GT(prop10.bands.size(), 0u);
156 }
157 mBands = prop10.bands;
158}
159
160void BroadcastRadioHalTest::TearDown() {
161 mTuner.clear();
162 mRadioModule.clear();
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700163 clearAndWait(mCallback, 1s);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700164}
165
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700166bool BroadcastRadioHalTest::openTuner() {
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700167 EXPECT_EQ(nullptr, mTuner.get());
168
169 if (radioClass == Class::AM_FM) {
170 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
171 }
172
173 Result halResult = Result::NOT_INITIALIZED;
174 auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
175 halResult = result;
176 if (result != Result::OK) return;
177 mTuner = ITuner::castFrom(tuner);
178 };
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700179 currentBandIndex = 0;
180 auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700181
182 EXPECT_TRUE(hidlResult.isOk());
183 EXPECT_EQ(Result::OK, halResult);
184 EXPECT_NE(nullptr, mTuner.get());
185 if (radioClass == Class::AM_FM && mTuner != nullptr) {
186 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
187
188 BandConfig halConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800189 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700190 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
191 halResult = result;
192 halConfig = config;
193 });
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800194 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700195 EXPECT_TRUE(halConfig.antennaConnected);
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800196 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700197
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800198 EXPECT_NE(nullptr, mTuner.get());
199 return nullptr != mTuner.get();
200}
201
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700202const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
203 static const BandConfig dummyBandConfig = {};
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800204
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700205 if (radioClass != Class::AM_FM) {
206 ALOGD("Not AM/FM radio, returning dummy band config");
207 return dummyBandConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800208 }
209
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700210 EXPECT_GT(mBands.size(), idx);
211 if (mBands.size() <= idx) {
212 ALOGD("Band index out of bound, returning dummy band config");
213 return dummyBandConfig;
214 }
215
216 auto& band = mBands[idx];
217 ALOGD("Returning %s band", toString(band.type).c_str());
218 return band;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800219}
220
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700221bool BroadcastRadioHalTest::nextBand() {
222 if (currentBandIndex + 1 >= mBands.size()) return false;
223 currentBandIndex++;
224
225 BandConfig bandCb;
226 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
227 .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
228 auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
229 EXPECT_EQ(Result::OK, hidlResult);
230 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
231 EXPECT_EQ(getBand(currentBandIndex), bandCb);
232
233 return true;
234}
235
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700236bool BroadcastRadioHalTest::getProgramList(
237 std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
238 ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
239 bool isListEmpty = true;
240 auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
241 ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
242 getListResult = result;
243 if (result != ProgramListResult::OK) return;
244 isListEmpty = (list.size() == 0);
245 if (!isListEmpty) cb(list);
246 };
247
248 // first try...
249 EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
250 .Times(AnyNumber());
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700251 auto hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700252 EXPECT_TRUE(hidlResult.isOk());
253 if (!hidlResult.isOk()) return false;
254
255 if (getListResult == ProgramListResult::NOT_STARTED) {
256 auto result = mTuner->startBackgroundScan();
257 EXPECT_EQ(ProgramListResult::OK, result);
258 getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
259 }
260 if (getListResult == ProgramListResult::NOT_READY) {
261 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
262
263 // second (last) try...
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700264 hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700265 EXPECT_TRUE(hidlResult.isOk());
266 if (!hidlResult.isOk()) return false;
267 EXPECT_EQ(ProgramListResult::OK, getListResult);
268 }
269
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700270 return !isListEmpty;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700271}
272
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700273/**
274 * Test IBroadcastRadio::openTuner() method called twice.
275 *
276 * Verifies that:
277 * - the openTuner method succeeds when called for the second time without
278 * deleting previous ITuner instance.
279 *
280 * This is a more strict requirement than in 1.0, where a second openTuner
281 * might fail.
282 */
283TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
284 if (skipped) return;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700285
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700286 ASSERT_TRUE(openTuner());
287
288 auto secondTuner = mTuner;
289 mTuner.clear();
290
291 ASSERT_TRUE(openTuner());
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700292}
293
294/**
295 * Test tuning to program list entry.
296 *
297 * Verifies that:
298 * - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
299 * - if the program list is NOT_STARTED, startBackgroundScan makes it completed
300 * within a full scan timeout and the next getProgramList call succeeds;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700301 * - if the program list is not empty, tuneByProgramSelector call succeeds;
302 * - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700303 */
304TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
305 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700306 ASSERT_TRUE(openTuner());
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700307
308 ProgramInfo firstProgram;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700309 bool foundAny = false;
310 do {
311 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
312 // don't copy the whole list out, it might be heavy
313 firstProgram = list[0];
314 };
315 if (getProgramList(getCb)) foundAny = true;
316 } while (nextBand());
317 if (HasFailure()) return;
318 if (!foundAny) {
319 printSkipped("Program list is empty.");
320 return;
321 }
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700322
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700323 ProgramInfo infoCb;
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700324 ProgramSelector selCb;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700325 EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700326 EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700327 .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700328 EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
329 .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykb8a2afe2017-08-01 10:52:18 -0700330 auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700331 ASSERT_EQ(Result::OK, tuneResult);
332 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700333 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700334 EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700335 EXPECT_EQ(infoCb.selector, selCb);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700336
337 bool called = false;
338 auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
339 called = true;
340 EXPECT_EQ(Result::OK, result);
341 EXPECT_EQ(selCb, info.selector);
342 });
343 ASSERT_TRUE(getResult.isOk());
344 ASSERT_TRUE(called);
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700345}
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800346
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700347/**
348 * Test that primary vendor identifier isn't used for standard program types.
349 *
350 * Verifies that:
351 * - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
352 * identifier for program types other than VENDORn.
353 */
354TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
355 if (skipped) return;
356 ASSERT_TRUE(openTuner());
357
358 for (auto ptype : kStandardProgramTypes) {
359 ALOGD("Checking %s...", toString(ptype).c_str());
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700360 ProgramSelector sel = {};
361 sel.programType = static_cast<uint32_t>(ptype);
362 sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700363
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700364 auto tuneResult = mTuner->tuneByProgramSelector(sel);
365 ASSERT_NE(Result::OK, tuneResult);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700366 }
367}
368
369/**
370 * Test that tune with unknown program type fails.
371 *
372 * Verifies that:
373 * - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
374 */
375TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
376 if (skipped) return;
377 ASSERT_TRUE(openTuner());
378
379 // Program type is 1-based, so 0 will be always invalid.
380 ProgramSelector sel = {};
381 auto tuneResult = mTuner->tuneByProgramSelector(sel);
382 ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
383}
384
385/**
386 * Test cancelling announcement.
387 *
388 * Verifies that:
389 * - cancelAnnouncement succeeds either when there is an announcement or there is none.
390 */
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700391TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
392 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700393 ASSERT_TRUE(openTuner());
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700394
395 auto hidlResult = mTuner->cancelAnnouncement();
396 EXPECT_EQ(Result::OK, hidlResult);
397}
398
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700399/**
400 * Test getImage call with invalid image ID.
401 *
402 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700403 * - getImage call handles argument 0 gracefully.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700404 */
405TEST_P(BroadcastRadioHalTest, GetNoImage) {
406 if (skipped) return;
407
408 size_t len = 0;
409 auto hidlResult =
410 mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
411
412 ASSERT_TRUE(hidlResult.isOk());
413 ASSERT_EQ(0u, len);
414}
415
416/**
417 * Test proper image format in metadata.
418 *
419 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700420 * - all images in metadata are provided out-of-band (by id, not as a binary blob);
421 * - images are available for getImage call.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700422 */
423TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
424 if (skipped) return;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700425 ASSERT_TRUE(openTuner());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700426
427 std::vector<int> imageIds;
428
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700429 do {
430 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
431 for (auto&& program : list) {
432 for (auto&& entry : program.base.metadata) {
433 EXPECT_NE(MetadataType::RAW, entry.type);
434 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
435 EXPECT_NE(0, entry.intValue);
436 EXPECT_EQ(0u, entry.rawValue.size());
437 if (entry.intValue != 0) imageIds.push_back(entry.intValue);
438 }
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700439 }
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700440 };
441 getProgramList(getCb);
442 } while (nextBand());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700443
444 if (imageIds.size() == 0) {
445 printSkipped("No images found");
446 return;
447 }
448
449 for (auto id : imageIds) {
450 ALOGD("Checking image %d", id);
451
452 size_t len = 0;
453 auto hidlResult =
454 mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
455
456 ASSERT_TRUE(hidlResult.isOk());
457 ASSERT_GT(len, 0u);
458 }
459}
460
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700461/**
462 * Test AnalogForced switch.
463 *
464 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700465 * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700466 */
467TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
468 if (skipped) return;
469 ASSERT_TRUE(openTuner());
470
471 bool forced;
472 Result halIsResult;
473 auto isCb = [&](Result result, bool isForced) {
474 halIsResult = result;
475 forced = isForced;
476 };
477
478 // set analog mode
479 auto setResult = mTuner->setAnalogForced(true);
480 ASSERT_TRUE(setResult.isOk());
481 if (Result::INVALID_STATE == setResult) {
482 // if setter fails, getter should fail too - it means the switch is not supported at all
483 auto isResult = mTuner->isAnalogForced(isCb);
484 ASSERT_TRUE(isResult.isOk());
485 EXPECT_EQ(Result::INVALID_STATE, halIsResult);
486 return;
487 }
488 ASSERT_EQ(Result::OK, setResult);
489
490 // check, if it's analog
491 auto isResult = mTuner->isAnalogForced(isCb);
492 ASSERT_TRUE(isResult.isOk());
493 EXPECT_EQ(Result::OK, halIsResult);
494 ASSERT_TRUE(forced);
495
496 // set digital mode
497 setResult = mTuner->setAnalogForced(false);
498 ASSERT_EQ(Result::OK, setResult);
499
500 // check, if it's digital
501 isResult = mTuner->isAnalogForced(isCb);
502 ASSERT_TRUE(isResult.isOk());
503 EXPECT_EQ(Result::OK, halIsResult);
504 ASSERT_FALSE(forced);
505}
506
Tomasz Wasilczyk002151c2017-11-22 09:43:06 -0800507static void verifyIdentifier(const ProgramIdentifier& id) {
508 EXPECT_NE(id.type, 0u);
509 auto val = id.value;
510
511 switch (static_cast<IdentifierType>(id.type)) {
512 case IdentifierType::AMFM_FREQUENCY:
513 case IdentifierType::DAB_FREQUENCY:
514 case IdentifierType::DRMO_FREQUENCY:
515 EXPECT_GT(val, 100u) << "Expected f > 100kHz";
516 EXPECT_LT(val, 10000000u) << "Expected f < 10GHz";
517 break;
518 case IdentifierType::RDS_PI:
519 EXPECT_GT(val, 0u);
520 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
521 break;
522 case IdentifierType::HD_STATION_ID_EXT: {
523 auto stationId = val & 0xFFFFFFFF; // 32bit
524 val >>= 32;
525 auto subchannel = val & 0xF; // 4bit
526 val >>= 4;
527 auto freq = val & 0x3FFFF; // 18bit
528 EXPECT_GT(stationId, 0u);
529 EXPECT_LT(subchannel, 8u) << "Expected ch < 8";
530 EXPECT_GT(freq, 100u) << "Expected f > 100kHz";
531 EXPECT_LT(freq, 10000000u) << "Expected f < 10GHz";
532 break;
533 }
534 case IdentifierType::HD_SUBCHANNEL:
535 EXPECT_LT(val, 8u) << "Expected ch < 8";
536 break;
537 case IdentifierType::DAB_SIDECC: {
538 auto sid = val & 0xFFFF; // 16bit
539 val >>= 16;
540 auto ecc = val & 0xFF; // 8bit
541 EXPECT_NE(sid, 0u);
542 EXPECT_GE(ecc, 0xA0u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
543 EXPECT_LE(ecc, 0xF6u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
544 break;
545 }
546 case IdentifierType::DAB_ENSEMBLE:
547 EXPECT_GT(val, 0u);
548 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
549 break;
550 case IdentifierType::DAB_SCID:
551 EXPECT_GT(val, 0xFu) << "Expected 12bit SCId (not 4bit SCIdS)";
552 EXPECT_LE(val, 0xFFFu) << "Expected 12bit id";
553 break;
554 case IdentifierType::DRMO_SERVICE_ID:
555 EXPECT_GT(val, 0u);
556 EXPECT_LE(val, 0xFFFFFFu) << "Expected 24bit id";
557 break;
558 case IdentifierType::DRMO_MODULATION:
559 EXPECT_GE(val, static_cast<uint32_t>(Modulation::AM));
560 EXPECT_LE(val, static_cast<uint32_t>(Modulation::FM));
561 break;
562 case IdentifierType::SXM_SERVICE_ID:
563 EXPECT_GT(val, 0u);
564 EXPECT_LE(val, 0xFFFFFFFFu) << "Expected 32bit id";
565 break;
566 case IdentifierType::SXM_CHANNEL:
567 EXPECT_LT(val, 1000u);
568 break;
569 case IdentifierType::VENDOR_PRIMARY_START:
570 case IdentifierType::VENDOR_PRIMARY_END:
571 // skip
572 break;
573 }
574}
575
576/**
577 * Test ProgramIdentifier format.
578 *
579 * Verifies that:
580 * - values of ProgramIdentifier match their definitions at IdentifierType.
581 */
582TEST_P(BroadcastRadioHalTest, VerifyIdentifiersFormat) {
583 if (skipped) return;
584 ASSERT_TRUE(openTuner());
585
586 do {
587 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
588 for (auto&& program : list) {
589 verifyIdentifier(program.selector.primaryId);
590 for (auto&& id : program.selector.secondaryIds) {
591 verifyIdentifier(id);
592 }
593 }
594 };
595 getProgramList(getCb);
596 } while (nextBand());
597}
598
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700599INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
600 ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
601
602} // namespace vts
603} // namespace V1_1
604} // namespace broadcastradio
605} // namespace hardware
606} // namespace android
607
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800608int main(int argc, char** argv) {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800609 ::testing::InitGoogleTest(&argc, argv);
610 int status = RUN_ALL_TESTS();
611 ALOGI("Test result = %d", status);
612 return status;
613}