blob: b54e9d8d3bc0e01b770094aa01d5cf5aa2ded281 [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
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -080019#include <android-base/logging.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070020#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>
Tomasz Wasilczyk06100b32017-12-04 09:53:32 -080025#include <broadcastradio-utils-1x/Utils.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070026#include <broadcastradio-vts-utils/call-barrier.h>
Dan Shi170a4452020-04-04 00:59:41 -070027#include <broadcastradio-vts-utils/hal-1.x-enum-utils.h>
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070028#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>
Dan Shi170a4452020-04-04 00:59:41 -070033#include <gtest/gtest.h>
34#include <hidl/GtestPrinter.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080035#include <hidl/HidlTransportSupport.h>
Dan Shi170a4452020-04-04 00:59:41 -070036#include <hidl/ServiceManagement.h>
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080037#include <utils/threads.h>
38
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070039#include <chrono>
40
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070041namespace android {
42namespace hardware {
43namespace broadcastradio {
44namespace V1_1 {
45namespace vts {
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080046
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070047using namespace std::chrono_literals;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080048
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070049using testing::_;
50using testing::AnyNumber;
51using testing::ByMove;
52using testing::DoAll;
Tomasz Wasilczyk24180092017-07-14 10:44:52 -070053using testing::Invoke;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070054using testing::SaveArg;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080055
Dan Shi170a4452020-04-04 00:59:41 -070056using broadcastradio::V1_0::vts::RadioClassFromString;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070057using broadcastradio::vts::CallBarrier;
58using V1_0::BandConfig;
59using V1_0::Class;
60using V1_0::MetaData;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -070061using V1_0::MetadataKey;
62using V1_0::MetadataType;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080063
Tomasz Wasilczyk31e86322017-12-05 09:36:11 -080064using broadcastradio::vts::clearAndWait;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -070065
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070066static constexpr auto kConfigTimeout = 10s;
67static constexpr auto kConnectModuleTimeout = 1s;
68static constexpr auto kTuneTimeout = 30s;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -070069static constexpr auto kEventPropagationTimeout = 1s;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070070static constexpr auto kFullScanTimeout = 1min;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -080071
Tomasz Wasilczykdd587702017-07-31 14:28:04 -070072static constexpr ProgramType kStandardProgramTypes[] = {
73 ProgramType::AM, ProgramType::FM, ProgramType::AM_HD, ProgramType::FM_HD,
74 ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
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
Dan Shi170a4452020-04-04 00:59:41 -070094class BroadcastRadioHalTest
95 : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
96 protected:
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -070097 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;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700105
106 sp<IBroadcastRadio> mRadioModule;
107 sp<ITuner> mTuner;
108 sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
109
110 private:
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700111 const BandConfig& getBand(unsigned idx);
112
113 unsigned currentBandIndex = 0;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700114 hidl_vec<BandConfig> mBands;
115};
116
117void BroadcastRadioHalTest::SetUp() {
Dan Shi170a4452020-04-04 00:59:41 -0700118 radioClass = RadioClassFromString(std::get<1>(GetParam()));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700119
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700120 // lookup HIDL service
Dan Shi170a4452020-04-04 00:59:41 -0700121 auto factory = IBroadcastRadioFactory::getService(std::get<0>(GetParam()));
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700122 ASSERT_NE(nullptr, factory.get());
123
124 // connect radio module
125 Result connectResult;
126 CallBarrier onConnect;
127 factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
128 connectResult = ret;
129 if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
130 onConnect.call();
131 });
132 ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
133
134 if (connectResult == Result::INVALID_ARGUMENTS) {
V,Anilkumar86f31e72022-07-05 23:39:38 +0530135 GTEST_SKIP() << "This device class is not supported.";
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800136 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700137 ASSERT_EQ(connectResult, Result::OK);
138 ASSERT_NE(nullptr, mRadioModule.get());
139
140 // get module properties
141 Properties prop11;
142 auto& prop10 = prop11.base;
143 auto propResult =
144 mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
145
146 ASSERT_TRUE(propResult.isOk());
147 EXPECT_EQ(radioClass, prop10.classId);
148 EXPECT_GT(prop10.numTuners, 0u);
Tomasz Wasilczyke192c392017-07-16 15:14:34 -0700149 EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
150 EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700151 if (radioClass == Class::AM_FM) {
152 EXPECT_GT(prop10.bands.size(), 0u);
153 }
154 mBands = prop10.bands;
155}
156
157void BroadcastRadioHalTest::TearDown() {
158 mTuner.clear();
159 mRadioModule.clear();
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700160 clearAndWait(mCallback, 1s);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700161}
162
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700163bool BroadcastRadioHalTest::openTuner() {
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700164 EXPECT_EQ(nullptr, mTuner.get());
165
166 if (radioClass == Class::AM_FM) {
167 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
168 }
169
170 Result halResult = Result::NOT_INITIALIZED;
171 auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
172 halResult = result;
173 if (result != Result::OK) return;
174 mTuner = ITuner::castFrom(tuner);
175 };
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700176 currentBandIndex = 0;
177 auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700178
179 EXPECT_TRUE(hidlResult.isOk());
180 EXPECT_EQ(Result::OK, halResult);
181 EXPECT_NE(nullptr, mTuner.get());
182 if (radioClass == Class::AM_FM && mTuner != nullptr) {
183 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
184
185 BandConfig halConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800186 Result halResult = Result::NOT_INITIALIZED;
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700187 mTuner->getConfiguration([&](Result result, const BandConfig& config) {
188 halResult = result;
189 halConfig = config;
190 });
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800191 EXPECT_EQ(Result::OK, halResult);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700192 EXPECT_TRUE(halConfig.antennaConnected);
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800193 }
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700194
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800195 EXPECT_NE(nullptr, mTuner.get());
196 return nullptr != mTuner.get();
197}
198
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700199const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
200 static const BandConfig dummyBandConfig = {};
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800201
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700202 if (radioClass != Class::AM_FM) {
203 ALOGD("Not AM/FM radio, returning dummy band config");
204 return dummyBandConfig;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800205 }
206
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700207 EXPECT_GT(mBands.size(), idx);
208 if (mBands.size() <= idx) {
209 ALOGD("Band index out of bound, returning dummy band config");
210 return dummyBandConfig;
211 }
212
213 auto& band = mBands[idx];
214 ALOGD("Returning %s band", toString(band.type).c_str());
215 return band;
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800216}
217
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700218bool BroadcastRadioHalTest::nextBand() {
219 if (currentBandIndex + 1 >= mBands.size()) return false;
220 currentBandIndex++;
221
222 BandConfig bandCb;
223 EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
224 .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
225 auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
226 EXPECT_EQ(Result::OK, hidlResult);
227 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
228 EXPECT_EQ(getBand(currentBandIndex), bandCb);
229
230 return true;
231}
232
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700233bool BroadcastRadioHalTest::getProgramList(
234 std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
235 ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
236 bool isListEmpty = true;
237 auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
238 ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
239 getListResult = result;
240 if (result != ProgramListResult::OK) return;
241 isListEmpty = (list.size() == 0);
242 if (!isListEmpty) cb(list);
243 };
244
245 // first try...
246 EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
247 .Times(AnyNumber());
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700248 auto hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700249 EXPECT_TRUE(hidlResult.isOk());
250 if (!hidlResult.isOk()) return false;
251
252 if (getListResult == ProgramListResult::NOT_STARTED) {
253 auto result = mTuner->startBackgroundScan();
254 EXPECT_EQ(ProgramListResult::OK, result);
255 getListResult = ProgramListResult::NOT_READY; // continue as in NOT_READY case
256 }
257 if (getListResult == ProgramListResult::NOT_READY) {
258 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
259
260 // second (last) try...
Tomasz Wasilczykfa3a5592017-08-03 11:06:09 -0700261 hidlResult = mTuner->getProgramList({}, getListCb);
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700262 EXPECT_TRUE(hidlResult.isOk());
263 if (!hidlResult.isOk()) return false;
264 EXPECT_EQ(ProgramListResult::OK, getListResult);
265 }
266
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700267 return !isListEmpty;
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700268}
269
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700270/**
271 * Test IBroadcastRadio::openTuner() method called twice.
272 *
273 * Verifies that:
274 * - the openTuner method succeeds when called for the second time without
275 * deleting previous ITuner instance.
276 *
277 * This is a more strict requirement than in 1.0, where a second openTuner
278 * might fail.
279 */
280TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700281 ASSERT_TRUE(openTuner());
282
283 auto secondTuner = mTuner;
284 mTuner.clear();
285
286 ASSERT_TRUE(openTuner());
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700287}
288
289/**
290 * Test tuning to program list entry.
291 *
292 * Verifies that:
293 * - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
294 * - if the program list is NOT_STARTED, startBackgroundScan makes it completed
295 * within a full scan timeout and the next getProgramList call succeeds;
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700296 * - if the program list is not empty, tuneByProgramSelector call succeeds;
297 * - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700298 */
299TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700300 ASSERT_TRUE(openTuner());
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700301
302 ProgramInfo firstProgram;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700303 bool foundAny = false;
304 do {
305 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
306 // don't copy the whole list out, it might be heavy
307 firstProgram = list[0];
308 };
309 if (getProgramList(getCb)) foundAny = true;
310 } while (nextBand());
311 if (HasFailure()) return;
312 if (!foundAny) {
V,Anilkumar86f31e72022-07-05 23:39:38 +0530313 GTEST_SKIP() << "Program list is empty.";
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700314 }
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700315
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700316 ProgramInfo infoCb;
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700317 ProgramSelector selCb;
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700318 EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700319 EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700320 .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700321 EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
322 .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
Tomasz Wasilczykb8a2afe2017-08-01 10:52:18 -0700323 auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700324 ASSERT_EQ(Result::OK, tuneResult);
325 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700326 EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
Tomasz Wasilczykf8866e72017-07-13 15:51:21 -0700327 EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
Tomasz Wasilczykdd130662017-08-03 18:08:57 -0700328 EXPECT_EQ(infoCb.selector, selCb);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700329
330 bool called = false;
331 auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
332 called = true;
333 EXPECT_EQ(Result::OK, result);
334 EXPECT_EQ(selCb, info.selector);
335 });
336 ASSERT_TRUE(getResult.isOk());
337 ASSERT_TRUE(called);
Tomasz Wasilczyka02b6ef2017-07-05 11:23:30 -0700338}
Tomasz Wasilczyk213170b2017-02-07 17:38:21 -0800339
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700340/**
341 * Test that primary vendor identifier isn't used for standard program types.
342 *
343 * Verifies that:
344 * - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
345 * identifier for program types other than VENDORn.
346 */
347TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700348 ASSERT_TRUE(openTuner());
349
350 for (auto ptype : kStandardProgramTypes) {
351 ALOGD("Checking %s...", toString(ptype).c_str());
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700352 ProgramSelector sel = {};
353 sel.programType = static_cast<uint32_t>(ptype);
354 sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700355
Tomasz Wasilczykda97a6d2017-08-04 12:57:29 -0700356 auto tuneResult = mTuner->tuneByProgramSelector(sel);
357 ASSERT_NE(Result::OK, tuneResult);
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700358 }
359}
360
361/**
362 * Test that tune with unknown program type fails.
363 *
364 * Verifies that:
365 * - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
366 */
367TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700368 ASSERT_TRUE(openTuner());
369
370 // Program type is 1-based, so 0 will be always invalid.
371 ProgramSelector sel = {};
372 auto tuneResult = mTuner->tuneByProgramSelector(sel);
373 ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
374}
375
376/**
377 * Test cancelling announcement.
378 *
379 * Verifies that:
380 * - cancelAnnouncement succeeds either when there is an announcement or there is none.
381 */
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700382TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700383 ASSERT_TRUE(openTuner());
Tomasz Wasilczyk24180092017-07-14 10:44:52 -0700384
385 auto hidlResult = mTuner->cancelAnnouncement();
386 EXPECT_EQ(Result::OK, hidlResult);
387}
388
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700389/**
390 * Test getImage call with invalid image ID.
391 *
392 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700393 * - getImage call handles argument 0 gracefully.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700394 */
395TEST_P(BroadcastRadioHalTest, GetNoImage) {
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700396 size_t len = 0;
397 auto hidlResult =
398 mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
399
400 ASSERT_TRUE(hidlResult.isOk());
401 ASSERT_EQ(0u, len);
402}
403
404/**
405 * Test proper image format in metadata.
406 *
407 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700408 * - all images in metadata are provided out-of-band (by id, not as a binary blob);
409 * - images are available for getImage call.
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700410 */
411TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700412 ASSERT_TRUE(openTuner());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700413
414 std::vector<int> imageIds;
415
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700416 do {
417 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
418 for (auto&& program : list) {
419 for (auto&& entry : program.base.metadata) {
420 EXPECT_NE(MetadataType::RAW, entry.type);
421 if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
422 EXPECT_NE(0, entry.intValue);
423 EXPECT_EQ(0u, entry.rawValue.size());
424 if (entry.intValue != 0) imageIds.push_back(entry.intValue);
425 }
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700426 }
Tomasz Wasilczykc1763a62017-07-25 10:01:17 -0700427 };
428 getProgramList(getCb);
429 } while (nextBand());
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700430
431 if (imageIds.size() == 0) {
V,Anilkumar86f31e72022-07-05 23:39:38 +0530432 GTEST_SKIP() << "No images found";
Tomasz Wasilczykba3e2542017-07-17 13:59:21 -0700433 }
434
435 for (auto id : imageIds) {
436 ALOGD("Checking image %d", id);
437
438 size_t len = 0;
439 auto hidlResult =
440 mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
441
442 ASSERT_TRUE(hidlResult.isOk());
443 ASSERT_GT(len, 0u);
444 }
445}
446
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700447/**
448 * Test AnalogForced switch.
449 *
450 * Verifies that:
Tomasz Wasilczykdd587702017-07-31 14:28:04 -0700451 * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700452 */
453TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
Tomasz Wasilczyk6e93c9c2017-07-25 10:53:50 -0700454 ASSERT_TRUE(openTuner());
455
456 bool forced;
457 Result halIsResult;
458 auto isCb = [&](Result result, bool isForced) {
459 halIsResult = result;
460 forced = isForced;
461 };
462
463 // set analog mode
464 auto setResult = mTuner->setAnalogForced(true);
465 ASSERT_TRUE(setResult.isOk());
466 if (Result::INVALID_STATE == setResult) {
467 // if setter fails, getter should fail too - it means the switch is not supported at all
468 auto isResult = mTuner->isAnalogForced(isCb);
469 ASSERT_TRUE(isResult.isOk());
470 EXPECT_EQ(Result::INVALID_STATE, halIsResult);
471 return;
472 }
473 ASSERT_EQ(Result::OK, setResult);
474
475 // check, if it's analog
476 auto isResult = mTuner->isAnalogForced(isCb);
477 ASSERT_TRUE(isResult.isOk());
478 EXPECT_EQ(Result::OK, halIsResult);
479 ASSERT_TRUE(forced);
480
481 // set digital mode
482 setResult = mTuner->setAnalogForced(false);
483 ASSERT_EQ(Result::OK, setResult);
484
485 // check, if it's digital
486 isResult = mTuner->isAnalogForced(isCb);
487 ASSERT_TRUE(isResult.isOk());
488 EXPECT_EQ(Result::OK, halIsResult);
489 ASSERT_FALSE(forced);
490}
491
Tomasz Wasilczyk002151c2017-11-22 09:43:06 -0800492static void verifyIdentifier(const ProgramIdentifier& id) {
493 EXPECT_NE(id.type, 0u);
494 auto val = id.value;
495
496 switch (static_cast<IdentifierType>(id.type)) {
497 case IdentifierType::AMFM_FREQUENCY:
498 case IdentifierType::DAB_FREQUENCY:
499 case IdentifierType::DRMO_FREQUENCY:
500 EXPECT_GT(val, 100u) << "Expected f > 100kHz";
501 EXPECT_LT(val, 10000000u) << "Expected f < 10GHz";
502 break;
503 case IdentifierType::RDS_PI:
504 EXPECT_GT(val, 0u);
505 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
506 break;
507 case IdentifierType::HD_STATION_ID_EXT: {
508 auto stationId = val & 0xFFFFFFFF; // 32bit
509 val >>= 32;
510 auto subchannel = val & 0xF; // 4bit
511 val >>= 4;
512 auto freq = val & 0x3FFFF; // 18bit
513 EXPECT_GT(stationId, 0u);
514 EXPECT_LT(subchannel, 8u) << "Expected ch < 8";
515 EXPECT_GT(freq, 100u) << "Expected f > 100kHz";
516 EXPECT_LT(freq, 10000000u) << "Expected f < 10GHz";
517 break;
518 }
519 case IdentifierType::HD_SUBCHANNEL:
520 EXPECT_LT(val, 8u) << "Expected ch < 8";
521 break;
522 case IdentifierType::DAB_SIDECC: {
523 auto sid = val & 0xFFFF; // 16bit
524 val >>= 16;
525 auto ecc = val & 0xFF; // 8bit
526 EXPECT_NE(sid, 0u);
527 EXPECT_GE(ecc, 0xA0u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
528 EXPECT_LE(ecc, 0xF6u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
529 break;
530 }
531 case IdentifierType::DAB_ENSEMBLE:
532 EXPECT_GT(val, 0u);
533 EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
534 break;
535 case IdentifierType::DAB_SCID:
536 EXPECT_GT(val, 0xFu) << "Expected 12bit SCId (not 4bit SCIdS)";
537 EXPECT_LE(val, 0xFFFu) << "Expected 12bit id";
538 break;
539 case IdentifierType::DRMO_SERVICE_ID:
540 EXPECT_GT(val, 0u);
541 EXPECT_LE(val, 0xFFFFFFu) << "Expected 24bit id";
542 break;
543 case IdentifierType::DRMO_MODULATION:
544 EXPECT_GE(val, static_cast<uint32_t>(Modulation::AM));
545 EXPECT_LE(val, static_cast<uint32_t>(Modulation::FM));
546 break;
547 case IdentifierType::SXM_SERVICE_ID:
548 EXPECT_GT(val, 0u);
549 EXPECT_LE(val, 0xFFFFFFFFu) << "Expected 32bit id";
550 break;
551 case IdentifierType::SXM_CHANNEL:
552 EXPECT_LT(val, 1000u);
553 break;
554 case IdentifierType::VENDOR_PRIMARY_START:
555 case IdentifierType::VENDOR_PRIMARY_END:
556 // skip
557 break;
558 }
559}
560
561/**
562 * Test ProgramIdentifier format.
563 *
564 * Verifies that:
565 * - values of ProgramIdentifier match their definitions at IdentifierType.
566 */
567TEST_P(BroadcastRadioHalTest, VerifyIdentifiersFormat) {
Tomasz Wasilczyk002151c2017-11-22 09:43:06 -0800568 ASSERT_TRUE(openTuner());
569
570 do {
571 auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
572 for (auto&& program : list) {
573 verifyIdentifier(program.selector.primaryId);
574 for (auto&& id : program.selector.secondaryIds) {
575 verifyIdentifier(id);
576 }
577 }
578 };
579 getProgramList(getCb);
580 } while (nextBand());
581}
582
Dan Shiac9cf442020-09-08 10:42:38 -0700583GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BroadcastRadioHalTest);
Dan Shi170a4452020-04-04 00:59:41 -0700584INSTANTIATE_TEST_CASE_P(
585 PerInstance, BroadcastRadioHalTest,
586 testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
587 IBroadcastRadioFactory::descriptor)),
588 ::testing::Values("AM_FM", "SAT", "DT")),
589 android::hardware::PrintInstanceTupleNameToString<>);
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -0700590
591} // namespace vts
592} // namespace V1_1
593} // namespace broadcastradio
594} // namespace hardware
595} // namespace android